- Author:
- danielsokolowski
- Posted:
- November 9, 2011
- Language:
- Python
- Version:
- 1.3
- Score:
- 1 (after 1 ratings)
Unfortunately the built in Django JSON serialzer encodes GeoDjango GeometyrField as WKT text. This snippet extends django's serializer and adds support for GEOJson format.
Built in JSON serializer output:
[{"pk": 1, ... "geopoint": "POINT (-76.5060419999999937 44.2337040000000030)" ... }]
GeoJSON serializer ouput:
[{"pk": 1, ... "geopoint": {"type": "Point",
"coordinates": [-76.503296000000006, 44.230956999999997],
"__GEOSGeometry__": [
"__init__",
[
"SRID=4326;POINT (-75.5129950000000036 44.2442360000000008)"
]
]
}]
Note: the "__GEOSGeometry__" is a class hint as defined by JSON-RCP
and used during deserilization.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | '''
Created on 2011-05-12
Updated on 2011-11-09 -- added desrializer support
@author: Daniel Sokolowski
Extends django's built in JSON serializer to support GEOJSON encoding
Requirements:
Install and setup geodjango (django.contrib.gis)
Install:
Add ``SERIALIZATION_MODULES = { 'geojson' : 'path.to.geojson_serializer' }`` to your
project ``settings.py`` file.
Usage:
from django.core import serializers
geojson = serializers.serialize("geojson", <Model>.objects.all())
Console Usage:
python manage.py dumpdata advertisements.advertiserlocation --format geojson --indent 4 --settings=settings_dev > fixture.geojson
--- check the file and verify that no extra characters were added at top and end of the dump
python manage.py loaddata fixture.geojson --settings=settings_dev
**Note:** however using plain JSON serializer/deserializer in the console will work just as fine.
'''
from django.core.serializers.json import DjangoJSONEncoder
from django.core.serializers.json import Serializer as OverloadedSerializer
from django.core.serializers.json import Deserializer
#from wadofstuff.django.serializers.python import Serializer as OverloadedSerializer
from django.utils import simplejson
from django.contrib.gis.db.models.fields import GeometryField
from django.contrib.gis.geos.geometry import GEOSGeometry
from django.utils import simplejson as json
from django.core.serializers.python import Deserializer as PythonDeserializer
class Serializer(OverloadedSerializer):
def handle_field(self, obj, field):
"""
If field is of GeometryField than encode otherwise call parent's method
"""
value = field._get_val_from_obj(obj)
if isinstance(field, GeometryField):
self._current[field.name] = value
else:
super(Serializer, self).handle_field(obj, field)
def end_serialization(self):
simplejson.dump(self.objects, self.stream, cls=DjangoGEOJSONEncoder, **self.options)
class DjangoGEOJSONEncoder(DjangoJSONEncoder):
"""
DjangoGEOJSONEncoder subclass that knows how to encode GEOSGeometry value
"""
def default(self, o):
""" overload the default method to process any GEOSGeometry objects otherwise call original method """
if isinstance(o, GEOSGeometry):
dictval = json.loads(o.geojson)
#raise Exception(o.ewkt)
dictval['__GEOSGeometry__'] = ['__init__', [o.ewkt]] #json class hint; see http://json-rpc.org/wiki/specification
return dictval
else:
super(DjangoGEOJSONEncoder, self).default(o)
def Deserializer(stream_or_string, **options):
"""
Deserialize a stream or string of JSON data.
"""
def GEOJsonToEWKT(dict):
"""
Convert to a string that GEOSGeometry class constructor can accept.
The default decoder would pass our geo dict object to the constructor which
would result in a TypeError; using the below hook we are forcing it into a
ewkt format. This is accomplished with a class hint as per JSON-RPC
"""
if '__GEOSGeometry__' in dict: # using class hint catch a GEOSGeometry definition
return dict['__GEOSGeometry__'][1][0]
return dict
if isinstance(stream_or_string, basestring):
stream = StringIO(stream_or_string)
else:
stream = stream_or_string
for obj in PythonDeserializer(simplejson.load(stream, object_hook=GEOJsonToEWKT), **options):
yield obj
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 7 months ago
Comments
Please login first before commenting.