4

My class structure is as follows -

class HelloWorld (object):
    def __init__(self, name, i, id):
        self.name = name
        self.i = i
        self.id = id

The I'm creating an object

p = HelloWorld('pj', 3456, '1234')

and passing this object to a definition, where I use jsonpickle.encode and jsonpickle.decode as follows

>>>print(type(p)) 
    <class 'HelloWorld'>
 >>>x = jsonpickle.encode(p)        
 >>>print(x)
    {"i": 3456, "name": "pj", "py/object": "__builtin__.HelloWorld", "id": "1234"}
 >>>y = jsonpickle.decode(x)
 >>>print(type(y))
    <class 'dict'>

I don't understand why I'm not able to decode it back to the original object, even though the distinguishing py/object is also present.

Can anyone please suggest what am I doing wrong?

Adding the code which generate's the dynamic class for above mentioned use case.

def _create_pojo(self, pojo_class_name, param_schema):

    #extracting the properties from the parameter 'schema'        
    pojo_properties = param_schema['properties']

    #creating a list of property keys
    pojo_property_list = []
    for key in pojo_properties:
        pojo_property_list.append(key)

    source = \
        "class %s (object):\n" % ( pojo_class_name )       
    source += "    def __init__(self, %s" % ', '.join(pojo_property_list) +"):\n" #defining __init__ for the class
    for prop in pojo_property_list: #creating a variable in the __init__ method for each property in the property list
        source += "        self.%s = %s\n" % (prop, prop)

    #generating the class code
    class_code = compile( source, "<generated class>", "exec" )
    fakeglobals = {}
    eval( class_code, {"object" : object}, fakeglobals )
    result = fakeglobals[ pojo_class_name ]        
    result ._source = source
    pprint.pprint(source)       

    self._object_types[ pojo_class_name ] = result
    return result
Blckknght
  • 100,903
  • 11
  • 120
  • 169
Piyush Jajoo
  • 1,095
  • 2
  • 18
  • 27
  • Are you doing this all in an interactive console, or is `HelloWorld` imported from a file? – Vasiliy Faronov Sep 14 '14 at 11:39
  • I tried this on python 2.7.7 and it is working OK using the code you posted. Can you check which python version you are working with? maybe this is the cause. – Yousef_Shamshoum Sep 14 '14 at 11:39
  • I cannot reproduce your problem. – Burhan Khalid Sep 14 '14 at 11:40
  • I'm generating this class automatically, inside my module. When I load this class specifically from a .py file in an interactive console, I can't reproduce the issue. But this seems to be something different. I you will see the value of "py/object" it's namespace is `__builtin__.HelloWorld`. And when I load it from outside, it says `__main__.HelloWorld`. The code to generate the class is - `eval( class_code, {"object" : object}, fakeglobals )` – Piyush Jajoo Sep 14 '14 at 13:51
  • .. is the class defined when you try to jsonpickle.decode(), or is it only defined dynamically when you encode it? – MatsLindh Sep 14 '14 at 14:49
  • Yes it is present the whole time. Actually, it is generated before I encode it, and it stays in the memory till I kill the interactive console. – Piyush Jajoo Sep 14 '14 at 15:03
  • Why is the namespace shown for my class is `__builtin__` but not `__main__`? – Piyush Jajoo Sep 14 '14 at 15:31
  • I can't reproduce either - @PiyushJajoo, post a complete program that demonstrate the problem, rather than code fragments. – Adam F Sep 14 '14 at 19:29
  • Added the code snippet, which generates the dynamic python class. – Piyush Jajoo Sep 15 '14 at 05:31

1 Answers1

4

The main problem here is, the class is not available while decoding, hence unable to decode it as an python object.

According to the JsonPickle documentation(http://jsonpickle.github.io/#module-jsonpickle), the object must be accessible globally via a module and must inherit from object (AKA new-style classes).

Hence followed following recipe, http://code.activestate.com/recipes/82234-importing-a-dynamically-generated-module/ . Using this you can generate dynamic module and load the classes dynamically. In this way while decoding the class will be accessible, and hence you can decode it back to python object.

Piyush Jajoo
  • 1,095
  • 2
  • 18
  • 27