【问题标题】:How to deserialize a GeoServer WFS GeoJSON?如何反序列化 GeoServer WFS GeoJSON?
【发布时间】:2019-01-16 00:46:53
【问题描述】:

TL:DR
我想将 GeoJSON 格式的 GeoServer WFS FeatureCollection 反序列化为 GeometryField/GeometryCollection


让我们从模型开始:

class Layer(models.Model):
    name = models.CharField(max_length=50)
    layer = GeometryCollectionField(null=True)

和序列化器:

class LayerSerializer(GeoFeatureModelSerializer):

    class Meta:
        model = Layer
        geo_field = 'layer'
        fields = ('id', 'name', 'layer')

现在 WFS GeoJSON 示例如下所示:

{
  "type": "FeatureCollection",
  "totalFeatures": 1,
    "features": [
      {
        "type": "Feature",
        "id": "some_id",
        "geometry": {
          "type": "MultiLineString",
          "coordinates": [
            [
              [4.538638998513776, 50.4674721021459],
              [4.5436667765043754, 50.47258379613634],
              [4.548444318495443, 50.47744374212726], 
              ...     
        },
        "geometry_name": "the_geom",
        "properties": {
          ...
        }
      }
    ],
    "crs": {
      "type": "name",
      "properties": {
        "name": "urn:ogc:def:crs:EPSG::4326"
      }
    }
  }
}

在尝试反序列化上述内容时,我收到以下错误:

"layer": [
  "Unable to convert to python object: 
  Invalid geometry pointer returned from \"OGR_G_CreateGeometryFromJson\"."
]

PS:我更喜欢一种不需要修改 GeoJSON 即可将其转换为 GeometryCollection 的解决方案(如果存在),因为我已经成功地做到了。

【问题讨论】:

  • 您找到解决方案了吗?我遇到了similar problem,欢迎提供任何提示
  • 你找到解决办法了吗?
  • @Nikko 我已经更新了我的解决方案,但我也喜欢你的解决方案!
  • @sc28 现在有两种可能的解决方案。一个是 Nikko 的,一个是我实际为解决此问题所做的。

标签: python django django-rest-framework geodjango django-rest-framework-gis


【解决方案1】:

我遇到了类似的情况。我认为问题在于解析 GeoJSON,因为它已转换为 Python 字典。我使用json.dump 将其恢复为 JSON 格式。

这就是我解决我的问题的方法。首先是为 GIS 字段制作字段序列化程序。就我而言,我使用了 GEOSGeometry:

#serializers.py
from django.contrib.gis.geos import GEOSGeometry
import json

class GeometryFieldSerializer(serializers.Field):
    def to_representation(self, instance):
        if instance.footprint:
            instance = json.loads(instance.footprint.geojson)
        else:
            instance = None
        return instance

    def to_internal_value(self, data):
        data = str(json.dumps(data))
        meta = {"footprint": GEOSGeometry(data)}
        return meta

在此之后,您可以将其合并到您的主序列化程序中。例如:

#serializers.py
class ModelSerializer(serializers.ModelSerializer):
    footprint = GeometryFieldSerializer(source='*')

    class Meta:
        model = Model

这是我要 POST 的示例 JSON:

{"name": "test",
"footprint": {"type": "Polygon",
              "coordinates": [[ [121.37, 14.02], [121.62, 14.02], 
                                [121.62, 14.26], [121.37, 14.26], 
                                [121.37, 14.02] ]]}
}

【讨论】:

  • 非常好的方法!我实际上已经忘记了这个问题。我也添加了我的解决方案,但我将您的解决方案标记为答案,因为它很好且完整并且使用纯 DRF 方法:)
【解决方案2】:

@Nikko 有一个非常好的和非常面向 DRF 的解决方案!

我实际上以非常相似的方式解决了这个问题,通过为地理服务器的特定响应创建一个解析器,它从 features 返回一个 geos.GeometryCollection

def parse_feature_collection(feature_collection: dict):
    """
    Parses a WFS response from GeoServer and creates a GeometryCollection from it.
    """
    geometries = [
        GEOSGeometry(json.dumps(feature.get('geometry')))
        for feature in feature_collection.get('features')
    ]
    return GeometryCollection(tuple(geometries), srid=4326)

然后在 celery 任务中使用它来更新相应的模型字段并在实例上执行一些其他耗时的方法(栅格化数据并应用一些计算)。

【讨论】:

    猜你喜欢
    • 2019-07-14
    • 1970-01-01
    • 1970-01-01
    • 2017-06-17
    • 2018-01-24
    • 2016-10-03
    • 2022-08-04
    • 2011-01-26
    • 1970-01-01
    相关资源
    最近更新 更多