On Aug 16, 2019, at 20:35, Kyle Stanley <aeros...@gmail.com> wrote: > > Speaking of examples, I think it would be helpful to provide a brief example > of ``object.__json__()`` being used for some added clarity. Would it be a > direct alias of ``json.dumps()`` with the same exact parameters and usage, or > would there be some substantial differences?
No, the idea is that it’s _used_ by dumps, as a substitute for passing a default function as an argument. Let’s say you have a tree class, and you want to serialize it to JSON as an array of arrays of etc. Here’s how you do it today: class MyTreeNode: # … def data(self) -> int: # … def children(self) -> List[MyTreeNode]: # … def jsonize_my_tree(obj): if isinstance(obj, MyTreeNode): return [obj.data(), *map(jsonize_my_tree, obj.children())] raise TypeError() myjson = json.dumps(my_thing_that_might_include_trees, default=jsonize_my_tree) This is only mildly inconvenient. But it does become worse if you have lots of classes you want to serialize. You need to write a default function somewhere that knows about all of your classes: def jsonize_my_things(obj): if isinstance(obj, MyTreeNode): return [obj.data(), jsonize_my_tree(obj.children())] if isinstance(obj, MyRational): return {'Fraction', obj.numerator, obj.denominator} if isinstance(obj, MyWinUTF16String): return str(obj) # … raise TypeError() Or you need to come up with a registry, or a protocol, or a singledispatch overload set, or some other way to let you write a separate function for each class and automatically combine them into one function you can pass to the default argument. The __json__ method would be a pre-made protocol that lets you just write the special handler for each class as part of that class, and not worry about how to combine them because the json module already takes care of that. So: class MyTreeNode: # … def data(self) -> int: # … def children(self) -> List[MyTreeNode]: # … def __json__(self): return [obj.data(), *map(jsonize_my_tree, obj.children())] class MyRational: # … def __json__(self): return {'Fraction', obj.numerator, obj.denominator} myjson = json.dumps(my_thing_that_might_include_trees_and_rationals_and_who_knows_what_else) Not a huge win with a single class, but with lots of classes you want custom serialization for, it can be very handy. Some of the third-party JSON modules, like simplejson, provide exactly this functionality (usually under the name for_json, because __json__ has double underscores and is therefore reserved for Python and its stdlib), and there are definitely people who like it. If you read the simplejson docs, and search for code that imports it, you can probably find lots of real-life examples. As I mentioned earlier in the thread, it’s very easy to write your own default function that calls for_json and partial that into dump/dumps/JSONEncoder (or to write a subclass of JSONEncoder that does the same thing without needing a default argument). And that has some nice benefits if you want to customize things (e.g., pass some of the encoder arguments into the for_json call), or if you prefer a registry or overload set to a method protocol, or whatever. So, I’m not sure this change is necessary. But I don’t see anything wrong with it if people really want it. _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/PTI5XMPFF473PMESGK7AGX6NEPKVCNTY/ Code of Conduct: http://python.org/psf/codeofconduct/