Инициализация классов из данных POST JSON - PullRequest
0 голосов
/ 28 апреля 2018

Я пишу приложение Django, которое отправит некоторые данные с сайта на сценарий python для обработки. Я планирую отправить эти данные в виде строки JSON (это не обязательно так). Некоторые из передаваемых значений в идеале должны быть экземплярами класса, однако это явно невозможно, и имя класса плюс любые аргументы, необходимые для инициализации класса, должны каким-то образом быть сериализованы в значение JSON, а затем десериализованы скриптом python. Этого можно достичь с помощью приведенного ниже кода, но у него есть несколько проблем:

Моя попытка

Я поместил все данные, необходимые для каждого класса, в список и использовал их для инициализации каждого класса:

import json


class Class1():

    def __init__(self, *args, **kwargs):
        for k, v in kwargs.items():
            setattr(self, k, v)
        self._others = args


class Bar():

    POTENTIAL_OBJECTS = {"RANGE": range,
                         "Class1": Class1}

    def __init__(self, json_string):
        python_dict = json.loads(json_string)
        for key, value in python_dict.items():
            if isinstance(value, list) and value[0] in Bar.POTENTIAL_OBJECTS:
                setattr(self, key, Bar.POTENTIAL_OBJECTS[value[0]](*value[1], **value[2]))
            else:
                setattr(self, key, value)

example = ('{ "key_1":"Some string", "key_2":["heres", "a", "list"],'
           '"key_3":["RANGE", [10], {}], "key_4":["Class1", ["stuff"], {"stuff2":"x"}] }')

a = Bar(example)

Проблемы с моим подходом

Помимо того, что, как правило, он немного грязный и не слишком элегантный, есть и другие проблемы. Некоторые списки в объекте JSON будут сгенерированы пользователем, и это, очевидно, создает проблемы, если пользователь использует ключ из POTENTIAL_OBJECTS. (В не упрощенной версии Bar будет иметь множество подклассов, каждый со вторым POTENTIAL_OBJECTS, поэтому отслеживать все потенциальные значения для проверки интерфейса было бы непросто).

Мой вопрос

Такое ощущение, что это должно быть достаточно обычной вещью, которая необходима, и должны быть какие-то стандартные схемы или способы достижения этого. Есть ли общий / лучший подход / метод для достижения этой цели?

РЕДАКТИРОВАТЬ: Я понял, что в одну сторону проблема состоит в том, чтобы заставить все ключи в POTENTIAL_OBJECTS начинаться с подчеркивания, а затем проверять наличие любых подчеркиваний в пользовательском вводе на входе , По-прежнему кажется, что должен быть лучший способ десериализации из JSON в более сложные объекты, чем строки / ints / bools / lists и т. Д.

1 Ответ

0 голосов
/ 29 апреля 2018

Вместо того, чтобы использовать один мастер-метод для превращения любого произвольного JSON в произвольную иерархию объектов Python, типичным шаблоном будет создание модели Django для каждого типа вещей, которые вы пытаетесь смоделировать. Отношения между ними будут затем моделироваться через поля отношений (ForeignKey, ManyToMany и т. Д., В зависимости от ситуации). Например, вы можете создать класс Employee, который моделирует сотрудника, и класс Paycheck. Paycheck может иметь поле ForeignKey с именем issued_to, которое относится к Employee.

Обратите также внимание, что любая схема, аналогичная описанной вами (где созданный пользователем JSON транслируется непосредственно в произвольные объекты Python), может иметь последствия для безопасности, потенциально позволяя пользователям выполнять произвольный код в контексте сервера Django, хотя, если Если бы вы попытались это сделать, то подход белого списка, начатый здесь, был бы приличным местом для начала, как способ сделать это безопасно.

Короче говоря, вы заново изобретаете большую часть того, что Django уже делает для вас. Функции Django ORM помогут вам создавать модели конкретных вещей, которые вас интересуют, проверять данные, безопасно превращать эти данные в объекты Python и даже сохранять экземпляры этих моделей в базе данных для последующего извлечения.

Тем не менее, если вы хотите проанализировать строку JSON непосредственно в иерархию объектов, вам придется выполнить полный обход вместо того, чтобы просто просматривать элементы верхнего уровня. Чтобы сделать это, вы должны изучить что-то вроде обхода в глубину , создавая новые экземпляры модели на каждом новом узле в иерархии. Если вы хотите проверить эти входные данные на стороне сервера, вам нужно будет повторить эту работу и в Javascript.

...