2

I'm hitting this exception with jsonpickle, when trying to pickle a rather complex object that unfortunately I'm not sure how to describe here. I know that makes it tough to say much, but for what it's worth:

>>> frozen = jsonpickle.encode(my_complex_object_instance)
>>> thawed = jsonpickle.decode(frozen)

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Python/2.7/site-packages/jsonpickle/__init__.py",
  line 152, in decode
    return unpickler.decode(string, backend=backend, keys=keys)
      :
      :
  File "/Library/Python/2.7/site-packages/jsonpickle/unpickler.py",
  line 336, in _restore_from_dict
    instance[k] = value
  File "/Library/Python/2.7/site-packages/botocore/vendored/requests/packages/urllib3/packages/ordered_dict.py",
  line 49, in __setitem__
    root = self.__root
AttributeError: 'OrderedDict' object has no attribute '_OrderedDict__root'

I don't find much of assistance when googling the error. I do see what looks like the same issue was resolved at some time past for simpler objects:

https://github.com/jsonpickle/jsonpickle/issues/33

The cited example in that report works for me:

>>> jsonpickle.decode(jsonpickle.encode(collections.OrderedDict()))
OrderedDict()
>>> jsonpickle.decode(jsonpickle.encode(collections.OrderedDict(a=1)))
OrderedDict([(u'a', 1)])

Has anyone ever run into this themselves and found a solution? I ask with the understanding that my case may be "differently idiosynchratic" than another known example.

Scott
  • 1,247
  • 3
  • 10
  • 21

1 Answers1

2

The requests module for me seems to be running into problems when I .decode(). After looking at the jsonpickle code a bit, I decided to fork it and change the following lines to see what was going on (and I ended up keeping a private copy of jsonpickle with the changes so I can move forward).

In jsonpickle/unpickler.py (in my version it's line 368), search for the if statement section in the method _restore_from_dict():

if (util.is_noncomplex(instance) or
    util.is_dictionary_subclass(instance)):
    instance[k] = value
else:
    setattr(instance, k, value)

and change it to this (it will logERROR the ones that are failing and then you can either keep the code in place or change your OrderedDict's version that have __root)

if (util.is_noncomplex(instance) or
    util.is_dictionary_subclass(instance)):
    # Currently requests.adapters.HTTPAdapter is using a non-standard
    # version of OrderedDict which doesn't have a _OrderedDict__root
    # attribute
    try:
        instance[k] = value
    except AttributeError as e:
        import logging
        import pprint
        warnmsg = 'Unable to unpickle {}[{}]={}'.format(pprint.pformat(instance), pprint.pformat(k), pprint.pformat(value))
        logging.error(warnmsg)
else:
    setattr(instance, k, value)
davfive
  • 323
  • 4
  • 13