【问题标题】:Initialize classes from POST JSON data从 POST JSON 数据初始化类
【发布时间】:2018-04-28 15:11:45
【问题描述】:

我正在编写一个 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 反序列化为比字符串/整数/布尔值/列表等更复杂的对象。

【问题讨论】:

    标签: python json django class deserialization


    【解决方案1】:

    典型的模式是为您尝试建模的每种类型的事物创建一个 Django 模型,而不是使用一个主方法将任意 JSON 转换为任意层次的 Python 对象。然后,它们之间的关系将通过relationship fields(ForeignKey、ManyToMany 等,视情况而定)建模。例如,您可以创建一个模拟员工的类 Employee 和一个类 Paycheck。然后Paycheck 可以有一个名为issued_toForeignKey 字段引用Employee

    还请注意,任何类似于您描述的方案(其中用户创建的 JSON 直接转换为任意 Python 对象)都会有安全隐患,可能允许用户在 Django 服务器的上下文中执行任意代码,但如果您要尝试一下,从这里开始的白名单方法将是一个不错的起点,可以安全地进行。

    简而言之,您正在重新发明 Django 已经为您完成的大部分工作。 Django ORM 功能将帮助您创建您感兴趣的特定事物的模型、验证数据、将这些数据安全地转换为 Python 对象,甚至将这些模型的实例保存在数据库中以供以后检索。

    也就是说,如果要将 JSON 字符串直接解析为对象层次结构,则必须进行完整遍历,而不是仅遍历顶级项。为此,您应该考虑执行类似depth-first traversal 的操作,在层次结构中的每个新节点处创建新模型实例。如果您想在服务器端验证这些输入,您还需要在 Javascript 中复制这项工作。

    【讨论】:

      猜你喜欢
      • 2021-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-16
      • 1970-01-01
      相关资源
      最近更新 更多