Обсуждение: register_adapter Json with custom JSONEncoder
Hello, how can I register an adapter with custom JSONEncoder, please. On Stack Overflow, https://stackoverflow.com/a/55939024/2556118 I have found to use Json class psycopg2.extensions.register_adapter(dict, psycopg2.extras.Json). But I need to use custom JSONEncoder because of bson.ObectId type # https://stackoverflow.com/a/16586277/2556118 import json from bson import ObjectId class JSONEncoder(json.JSONEncoder): def default(self, o): if isinstance(o, ObjectId): return str(o) return supper().JSONEncoder.default(self, o) There is a parameter dumps in Json.__init__(self, adapted, dumps=None), but how to set it when used with register_adapter(), https://www.psycopg.org/docs/extensions.html#psycopg2.extensions.register_adapter? Should I write myself the whole Json class? Thank you in advance, Hans
Hello, On Mon, 13 Jul 2020 at 16:49, Hans Ginzel <hans@matfyz.cz> wrote: [...] > But I need to use custom JSONEncoder because of bson.ObectId type > # https://stackoverflow.com/a/16586277/2556118 This doc page has more examples: https://www.psycopg.org/docs/extras.html#json-adaptation > There is a parameter dumps in Json.__init__(self, adapted, dumps=None), > but how to set it when used with register_adapter(), You can use a partial function for instance, of the like of: `lambda obj: Json(obj, dumps=mydumps)`. > https://www.psycopg.org/docs/extensions.html#psycopg2.extensions.register_adapter? > > Should I write myself the whole Json class? No, if you really want you can subclass the one we provide and only override `_dumps()`: the one psycopg2 provides consists in pretty much: class Json(object): def __init__(self, adapted, dumps=None): self.adapted = adapted self._dumps = dumps or json.dumps def dumps(self, obj): return self._dumps(obj) so you can either create your instances using a wrapper in register_adapter, or subclass the _dumps() method of the class: as you can see it is equivalent. I guess the first method is better as you don't need to care about the implementation of the `Json` class. -- Daniele
On Mon, Jul 13, 2020 at 05:15:19PM +0100, Daniele Varrazzo wrote:
>You can use a partial function for instance, of the like of: `lambda
>obj: Json(obj, dumps=mydumps)`.
Thank you, Daniele.
I have (succesfully) tried
from psycopg2.extras import Json
from json import JSONEncoder
from bson import ObjectId
class JSONEncoder(JSONEncoder):
def default(self, o):
if isinstance(o, ObjectId):
return str(o)
return supper().default(self, o)
jsonEncoder = JSONEncoder()
#psycopg2.extensions.register_adapter(dict, Json)
psycopg2.extensions.register_adapter(dict, lambda o: Json(o, dumps=jsonEncoder.encode))
and variants like
import json
psycopg2.extensions.register_adapter(dict, lambda o: Json(o, dumps = lambda oo: json.dumps(oo, default=str)))
or
from bson import json_util
psycopg2.extensions.register_adapter(dict, lambda o: Json(o, dumps=json_util.dumps))
I choosed the first one because of cached Encoder and cleanest way.
Best regards,
Hans