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
,因为我已经成功地做到了。
我遇到了类似的情况。我认为问题在于解析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
这是我的示例JSON到POST:
{"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] ]]}
}
@@ Nikko有一个非常好的,非常面向DRF的解决方案!
我实际上以非常相似的方式解决了这一问题,方法是为地理服务器的特定响应创建一个解析器,该解析器从geos.GeometryCollection
返回一个features
:
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任务内部使用了该属性以更新相应的模型字段,并在实例上也执行其他一些耗时的方法(栅格化数据并应用一些计算)。