Sean, Eric, those interested,
Another option is to abandon my abstracton idea, and just get ride of
dumps/dump/load/loads/encode/decode in favour of:
# 'feature' in this example, could be geojson.GeoJSON.to_instance({"type":
..., ...})
feature = geojsonlib.Feature(geometry=geojsonlib.Point(coordinates=[x, y]))
d = dict(feature)
myjsonlib.[encode|write|dumps](d, ...)
(Where myjsonlib is simplejson, json.py, jsonlib, cjson etc)
since this is all that needs to happen, and is exactly what each 'codec' in
my hooks idea would accomplish, except we gain the advantage of not having
to track each JSON library api, give the user (us too) one less level of
indirection to follow.
We'd also not have dependancy on simplejson, and have no other dependancies.
The GeoJSON spec declares that geojson can have arbitrary members, this is
still possible,
just less convienient syntax:
d = {"blog":
{"placename": "California",
"location": feature}
}
json1 = cjson.write(d)
json 2 = simplejson.dumps(d, encoding="utf-8")
So, now I think this is (probably) the right way to go... what do you think?
2008/6/19 Matthew Russell <[EMAIL PROTECTED]>:
> Sean,
>
> I've done a bit of digging, an unfortunatly, writing a cjson codec would be
> non-trivial, or impossible; unless the author(s) of that package provided a
> hook (like JSONEcoder.default is)
>
> jsonlib's write (equivilent of dumps/encode) has an 'on_unknown' hook, so
> that'd work,
> as would all other pure-python json libraries.
>
> A jsonlib codec might look like:
>
> class JsonlibCodec(object):
> def encode(self, obj, **kwargs):
> def on_unknown(value):
> d = dict(gejsonlib.GeoJSON.to_instance(value))
> return jsonlib.write(d)
> kwargs["on_unknown"] = on_unknown
> return jsonlib.write(obj, **kwargs)
>
> def decode(self, json, **kwargs):
> obj_hooj = kwargs.get("object_hook", hoo)
> o = jsonlib.read(json)
> if obj_hook:
> o = obj_hook(o)
> return o
>
> A json-py codec might look like:
>
>
> import json
> class JsonPyCodec(object):
> def encode(self, obj, *args, **kwargs):
> json_writer = json.JsonWriter()
> try:
> return json_writer.write(obj)
> except json.WriteException: # not a python object corrospondng to
> 'primative' json type
> return
> json_writer.write(dict(geojsonlib.GeoJSON.to_instance(obj)))
>
> def decode(obj, *args, **kwargs):
> obj_hook = kwargs.pop("object_hook", lambda x: obj)
> return json.JsonReader().read(obj_hooj(obj))
>
>
> Matt
>
>
>
> 2008/6/18 Matthew Russell <[EMAIL PROTECTED]>:
>
>> Sean,
>>
>>
>> I'd be ok with keeping loads/dumps as functions in geojsonlib/__init__.py
>> They could even raise DepricationWaring.
>>
>> I've seen r1113's encoding.py, and it's similar to what I had in mind, but
>> not quite.
>>
>> There's an extra level of indirection, geojsonlib/__init__ would define:
>>
>> # nb. in the following, geojsonlib.encoding is renamed to codecs
>>
>> def encode(obj, codec=None, *args, **kwargs):
>> codec = codec or geojsonlib.codecs.default
>> return codec.encode(obj, *args, **kwargs)
>>
>> decode would be much the same.
>> Then I can write a CJson() codec (which defines encode and decode), and
>> have that used instead.
>>
>> in geojsonlib.codecs, my hacked up version of the module goes something
>> like:
>>
>> class JSONCodec(objet):
>> def encode(self, obj, **kwargs): raise NotImplemented
>> def decode(self, obj, **kwargs): raise NotImplemented
>>
>> try:
>> import simplejson
>> except ImportError:
>> default = Codec()
>> else:
>> class SimpleJSONCodec(JSONCodec):
>>
>> def encode(self obj, **kwargs):
>> return simplejson.dumps(obj, **kwargs)
>>
>> def decode(self, obj, **kwargs):
>> return simplejson.loads(obj, **kwargs)
>>
>> default = SimepJSONCodec
>>
>>
>> Cheers,
>> Matt
>>
>> 2008/6/18 Sean Gillies <[EMAIL PROTECTED]>:
>>
>> Matt,
>>>
>>> What would you think about keeping geojsonlib.dumps/loads as is for
>>> convenience and just raise exceptions if simplejson can't be imported?
>>> See rev 1113 -- I marked the dump/load feature as an "extra" in setup.py.
>>>
>>> Sean
>>>
>>> Matthew Russell wrote:
>>> > Hi,
>>> >
>>> > this is a proposal which Sean already +1'd in the recent "[Community]
>>> [Fwd:
>>> > [Geojson] GeoJSON 1.0 Released]" thread.
>>> >
>>> > The proposal is to remove the reliance on simplejson from geojsonlib
>>> (but
>>> > keeping simplejson as the default).
>>> >
>>> > I'n slight alteration to my previous api suggestion for the interface
>>> for
>>> > simplejson's peers,
>>> > I'd like to change the api from:
>>> >
>>> > geojsonlib.{dumps, dump, loads, load}
>>> >
>>> > to:
>>> >
>>> > json = geojsonlib.encode(obj, codec="geojsonlib.defaultcodec",
>>> *codec_args,
>>> > **codec_kwargs)
>>> > - where obj is any python object supporting the geointerface, or a
>>> mapping
>>> > - returns unicode or str
>>> >
>>> > obj = geojsonlib.decode(json, codec="geojsonlib.defaultcodec",
>>> *codec_args,
>>> > **codec_kwargs)
>>> >
>>> > - where 'json' is a unicode or str instance.
>>> > - reutrns a geojsonlib.GeoJSON instance or subclass thereof.
>>> >
>>> > The primary motivation for this is file encoding.
>>> > I'd like to keep the serialisation to file-like objects within the
>>> control
>>> > of the user at the I/O boundaries.
>>> > Removing the dump and load functions from geojsonlib would acheive
>>> this.
>>> > I also think the names encode and decode are better, since load and
>>> dumps
>>> > indicate serialization to disk.
>>> >
>>> > So, does anyone object if the api changes from:
>>> > geojsonlib.dumps -> geojson.encode
>>> > geojsonlib.loads -> geojson.decode
>>> > geojsonlib.dump -> file_like.write(geojsonlib.encode(obj))
>>> > geojsonlib.load -> geojsonlib.decode(file_like.read())
>>> >
>>> > ?
>>> >
>>> > Once this is implemented, simplejson will only be required in the
>>> default
>>> > case:
>>> >
>>> > .encode(obj), .decode(obj)
>>> >
>>> > and not if you want to use another JSON library, and have an adapter:
>>> >
>>> > e.g
>>> >
>>> > class CjsonEncoder:
>>> > def encode(self, obj):
>>> > ...
>>> >
>>> > .encode(obj, codec=CjsonEncoder)
>>> >
>>> > N.B:
>>> >
>>> > 'codec' can be a dotted path, or any namespace with a .encode or
>>> .decode
>>> > callable attribute as releveant.
>>> >
>>> > --
>>> > Cheers,
>>> > Matt
>>> >
>>> >
>>> >
>>> >
>>> ------------------------------------------------------------------------
>>> >
>>> > _______________________________________________
>>> > Community mailing list
>>> > [email protected]
>>> > http://lists.gispython.org/mailman/listinfo/community
>>>
>>> _______________________________________________
>>> Community mailing list
>>> [email protected]
>>> http://lists.gispython.org/mailman/listinfo/community
>>>
>>
>>
>>
--
Cheers,
Matt
_______________________________________________
Community mailing list
[email protected]
http://lists.gispython.org/mailman/listinfo/community