1

I've searched SO's posts but couldn't figure out solution to my problem. I've seen bunch of SO posts which explains how to serialize python objects haven't found anything which explains how to serialize dictionary of list of python objects.

Here's the problem statement and sample use-case:

import json  
import collections    
from collections import defaultdict     

class A:
    def __init__(self, a1_list=[], a2_str=None):
        self.a1_list  = []
        self.a2_str = a2_str

class B:
     def __init__(self, list_of_A_objects=[], b2_str=None):
        self.list_of_A_objects = list_of_A_objects
        self.b2_str = b2_str

if __name__ == "__main__":
     a1 = A([1, 2, 3], '123')
     a2 = A([4, 5, 6], '456')
     b1 = B([a1, a2], '123-456')

     a3 = A([11, 22, 33], '112233')
     a4 = A([44, 55, 66], '445566')
     b2 = B([a3, a4], '112233-445566')

     dict_b = defaultdict(list)
     dict_b['b'].append(b1)
     dict_b['b'].append(b2)
     json.dumps(dict_b) 

Error is thrown at the last line json.dumps(dict_b) saying

TypeError: Object of type 'B' is not JSON serializable

EDIT:

I've tried pickle as @coldspeed has suggested in the comments, but I'd like to view the dumped JSON with a text editor. If I use pickle, I can't view it since it is dumped in binary format.

Am I doing anything incorrectly?

8

1 Answer 1

2

You could define a method to dump you classe to json with json.dumps.

import json  
from collections import defaultdict

class A:
    def __init__(self, items=[], string=None):
        self.items = items
        self.string = string

    def toJSON(self):
        return json.dumps(self, default=lambda obj: obj.__dict__)#, sort_keys=True, indent=4)


if __name__ == "__main__":
    a1 = A([1, 2, 3], '123')
    a2 = A([4, 5, 6], '456')
    b1 = A([a1, a2], '123-456')
    print(b1.toJSON())
    # Result: {"items": [{"items": [1, 2, 3], "string": "123"}, {"items": [4, 5, 6], "string": "456"}], "string": "123-456"}

    a3 = A([11, 22, 33], '112233')
    a4 = A([44, 55, 66], '445566')
    b2 = A([a3, a4], '112233-445566')

    dict_b = defaultdict(list)
    dict_b['b'].append(b1.toJSON())
    dict_b['b'].append(b2.toJSON())
    print(json.dumps(dict_b))

Disadvantages You always will have a serialized version of your class. To avoid this side effect you can set a new method to turn back it to a dict with loads

def to_dict(self):
    return json.loads(self.toJSON())

And at defaultdict append object.to_dict

dict_b = defaultdict(list)
dict_b['b'].append(b1.to_dict())
dict_b['b'].append(b2.to_dict())
print(json.dumps(dict_b))
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.