Matt, That seems good to me. I would, however, very much like to keep the optional dependence on simplejson for dumps/loads. BTW, simplejson is in the 2.6/3.0 standard library:
http://bugs.python.org/issue2750 Sean Matthew Russell wrote: > 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
