Структура дерева зефира Python с полиморфизмом - PullRequest
1 голос
/ 11 марта 2019

У меня есть следующий код для древовидной структуры:

class Node:
    def __init__(self, node_id: str):
        self.node_id = node_id
        self.children = []

    def add_child(self, node: 'Node'):
        if isinstance(node, Node):
            self.children.append(node)


class ValueNode(Node):
    def __init__(self, value: bool, **kwargs):
        Node.__init__(self, **kwargs)
        self.value = value


class LogicNode(Node):
    def __init__(self, logic_operator: str, **kwargs):
        Node.__init__(self, **kwargs)
        self.logic_operator = logic_operator


a = Node("a")
b = LogicNode("or", node_id="b")
c = ValueNode(True, node_id="c")
d = ValueNode(False, node_id="d")

b.add_child(c)
b.add_child(d)
a.add_child(b)

Как я могу сериализовать объект a в json и обратно в объект python, сохранив правильные типы и древовидную структуру?

То, что я пробовал:

Я пытаюсь сериализовать эту древовидную структуру в json для отправки пользовательскому интерфейсу через API.Я узнал о зефире, но, к сожалению, я не могу понять, как это сделать.Я имею это как схемы atm.

class NodeSchema(Schema):
    node_id = fields.String()
    children = fields.Nested('self', many=True)

    @post_load
    def load(self, data):
        return Node(**data)


class ValueNodeSchema(NodeSchema):
    value = fields.Boolean()


class LogicNodeSchema(NodeSchema):
    logic_operator = fields.String()

Здесь проблема в том, что при сериализации в json присутствуют только атрибуты Node, даже если дочерние элементы являются логическим узлом или узлом значения (что-то вроде ожидаемого).Я узнал о зефире-одино-скеме здесь github , но я не могу использовать его, потому что с этим я должен заменить:

# In NodeSchema
children = fields.Nested('self', many=True)

на:

class SomeNodeSchema(OneOfSchema):
    type_schemas = {
        'node': NodeSchema,
        'logic_node': LogicNodeSchema,
        'value_node': ValueNodeSchema,
    }

    def get_obj_type(self, obj):
        if isinstance(obj, LogicNode):
            return 'logic_node'
        if isinstance(obj, ValueNode):
            return 'value_node'
        elif isinstance(obj, Node):
            return 'node'

# In NodeSchema
children = fields.Nested(SomeNodeSchema, many=True)

, ноэто приводит к круговому импорту, который делает невозможным.

1 Ответ

1 голос
/ 11 марта 2019

Я узнал о зефире-однофсхеме

Хотя это и не интегрировано в ядро, я думаю, что зефир-однофсхема - это рекомендуемый способ полиморфизма.

это приводит к круговому импорту

Вы можете передать имя в виде строки, чтобы решить проблему циклического импорта.

    children = fields.Nested('SomeNodeSchema', many=True)
...