ferk86
ferk86

Reputation: 2345

Avoid jsonpickle using py/id pointer to another object

When an object is serialized to json using jsonpickle, I noticed objects such as datetime are stored once then future uses are stored as references value such as {"py/id":1}. Is it possible store actual value instead of reference? This reference seems hidden and would be confusing when interacting directly with database.

Ex. class MyClass: def __init__(self, eee): now = datetime.datetime.utcnow() self.ddd = now self.ddd2 = now self.ddd3 = now

Json is {"py/object": "__main__.MyClass", "py/state": {"ddd": {"py/object": "datetime.datetime", "__reduce__": [{"py/type": "datetime.datetime"}, ["B+IBFhYJCwx9oQ=="]]}, "ddd2": {"py/id": 1}, "ddd3": {"py/id": 1}, "eee": "fwaef"}}

Upvotes: 8

Views: 5430

Answers (4)

unie
unie

Reputation: 311

One should understand the difference between make_refs=False and unpicklable=False when trying to simplify the jsonpickle encoding output:

make_refs=False will prevent jsonpickle from creating references (those py/id attributes) to identical objects. The references make the output more compact, but less readable, and thus one might prefer make_refs=False at the expense of a larger file. However, the resulting file can still be decoded back to a Python object.

unpicklable=False means literally that the jsonpickle output cannot be unpickled, i.e. decoded, to its original type. The output is again more readable, but if the object you're encoding contains non-native datatypes (i.e. classes defined by you), the encoding output will store the value of those objects' properties, but if you try to decode the file back to its python representation, the objects will be dicts, not instances of your classes.

Upvotes: 5

Badr El Mazaz
Badr El Mazaz

Reputation: 124

Try to use unpicklable attrubute set as False

import datetime
import jsonpickle

class MyClass:
    def __init__(self, eee):
        now = datetime.datetime.utcnow()
        self.ddd = now
        self.ddd2 = now
        self.ddd3 = now

my_object = MyClass('hi')
jsonpickle.encode(my_object, unpicklable=False)

Upvotes: 0

pravinbhogil
pravinbhogil

Reputation: 695

New way of doing. Above answer is old.

jsonpickle.encode(my_object, unpicklable=False)

Upvotes: 10

Adam
Adam

Reputation: 486

You can use the make_refs parameter when invoking jsonpickle.encode:

import datetime
import jsonpickle

class MyClass:
    def __init__(self, eee):
        now = datetime.datetime.utcnow()
        self.ddd = now
        self.ddd2 = now
        self.ddd3 = now

my_object = MyClass('hi')
jsonpickle.encode(my_object, make_refs=False)

From the documentation here:

make_refs – If set to False jsonpickle’s referencing support is disabled. Objects that are id()-identical won’t be preserved across encode()/decode(), but the resulting JSON stream will be conceptually simpler. jsonpickle detects cyclical objects and will break the cycle by calling repr() instead of recursing when make_refs is set False.

Upvotes: 8

Related Questions