admin管理员组

文章数量:1296293

I have a couple of classes instantiate basic types like str, int, float, list, dict's but also other classes that contains similar types. Essentially I have nested layers of objects. It is converted this way so data can be represented as objects and manipulated later. Once all the processing is done I want to export the data into a dictionary so it can be stored as a Json object on a database. Is this common? Are there libraries that help you do this.

So far I was going to implement a function that converts the top level class and nested objects into dictionary nested output. I'm worried I will get stack overflow from the recursion I will be using to

def getObjectAsDict(self):
    d = {}

    for name_of_attr in dir(some_class):
        if name_of_attr.startswith("_"):
            continue

        value_of_attr = getattr(some_class, name_of_attr)

        if isinstance(value_of_attr, str):
            pass
        elif isinstance(value_of_attr, int):
            pass
        elif isinstance(value_of_attr, float):
            pass
        elif isinstance(value_of_attr, bool):
            pass
        elif isinstance(value_of_attr, list):
            for idx, item in enumerate(value_of_attr):
                # some recursion logic here
        elif isinstance(value_of_attr, dict):
            for key, value in value_of_attr.items():
                # some recursion logic here
        elif isinstance(value_of_attr, ComplexObject):
            value_of_attr = value_of_attr.getObjectAsDict()
                # some recursion logic here
        else:
            continue
        d[name_of_attr] = value_of_attr

I have a couple of classes instantiate basic types like str, int, float, list, dict's but also other classes that contains similar types. Essentially I have nested layers of objects. It is converted this way so data can be represented as objects and manipulated later. Once all the processing is done I want to export the data into a dictionary so it can be stored as a Json object on a database. Is this common? Are there libraries that help you do this.

So far I was going to implement a function that converts the top level class and nested objects into dictionary nested output. I'm worried I will get stack overflow from the recursion I will be using to

def getObjectAsDict(self):
    d = {}

    for name_of_attr in dir(some_class):
        if name_of_attr.startswith("_"):
            continue

        value_of_attr = getattr(some_class, name_of_attr)

        if isinstance(value_of_attr, str):
            pass
        elif isinstance(value_of_attr, int):
            pass
        elif isinstance(value_of_attr, float):
            pass
        elif isinstance(value_of_attr, bool):
            pass
        elif isinstance(value_of_attr, list):
            for idx, item in enumerate(value_of_attr):
                # some recursion logic here
        elif isinstance(value_of_attr, dict):
            for key, value in value_of_attr.items():
                # some recursion logic here
        elif isinstance(value_of_attr, ComplexObject):
            value_of_attr = value_of_attr.getObjectAsDict()
                # some recursion logic here
        else:
            continue
        d[name_of_attr] = value_of_attr
Share Improve this question edited Feb 12 at 18:56 tyleax asked Feb 12 at 4:43 tyleaxtyleax 1,7883 gold badges22 silver badges51 bronze badges 1
  • How about just json.dumps(my_object, default=lambda o: o.__dict__ ) – JonSG Commented Feb 12 at 17:47
Add a comment  | 

2 Answers 2

Reset to default 0

The Python JSON Library allows you to pass in custom logic to handle serializing custom objects.

For example, if you have two classes, Foo and Bar with Foo instances referencing Bar instances:

class Foo:
    def __init__(self, bar, x):
        self.bar = bar
        self.x = x

class Bar:
    def __init__(self, y):
        self.y = y

You can create a function that tells the JSON library how you want Foo and Bar objects to be turned into JSON serializable data — any time the JSON library comes across an object that it doesn't know how into JSON, it passes it to this function:

def foobar_serializer(obj):
    if isinstance(obj, Foo):
        return {"type": "Foo", "bar": obj.bar, "x": obj.x}
    elif isinstance(obj, Bar):
        return {"type": "Bar", "y": obj.y}
    raise TypeError(f'Cannot serialize object of {type(obj)}')

You then pass this handler into the JSON dump/dumps function:

import json

my_foo = Foo(Bar(1), 2)
result = json.dumps(my_foo, default=foobar_serializer)
print(result)  # {"type": "Foo", "bar": {"type": "Bar", "y": 1}, "x": 2}

Note that when foobar_serializer is handling objects of type Foo, it doesn't need to also handle objects of type Bar — when the JSON dump/dumps function gets to bar it will call the function again.

You can use custom encoder.

Example from documentation

import json
class ComplexEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, complex):
            return [obj.real, obj.imag]
        # Let the base class default method raise the TypeError
        return super().default(obj)

json.dumps(2 + 1j, cls=ComplexEncoder)

ComplexEncoder().encode(2 + 1j)

list(ComplexEncoder().iterencode(2 + 1j))

Example for nested objects

from __future__ import annotations

class Foo:
    def __init__(self, name: str, children: list[Foo] = None):
        self.name = name
        self.children = children or []

    name: str
    children: list[Foo]

    def serialize(self):
        return {"name": self.name, "children": self.children}


example_child_1 = Foo("example_child_1", [])
example_child_2 = Foo("example_child_2", [])
example = Foo("example", [example_child_1, example_child_2])


import json
class CustomEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, Foo):
            return obj.serialize()
        # Let the base class default method raise the TypeError
        return super().default(obj)

json.dumps(example, cls=CustomEncoder)

本文标签: Python How to convert complex nested classes into dictionaryStack Overflow