将 JSON 架构与棉花糖序列化结合使用



我正在使用棉花糖对JSON字符串进行序列化和反序列化。从棉花糖 API 文档 (https://marshmallow.readthedocs.io/en/3.0/api_reference.html) 中,您似乎已经指定了一个字段列表(除非使用 Meta )它们的数据类型。例如:

Marital_Status=Fields.Str()
Employer=Fields.Str()
ContactInfo(data) #where ContactInfo is a class not shown here

但是,我已经有一个指定字段和数据类型的 JSON 架构。例如:

the_template_schema={
"definitions": {},
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://example.com/root.json",
"type": "object",
"title": "The Root Schema",
"properties": {
 "Marital_Status": {
  "$id": "#/properties/Marital_Status",
  "type": "string",
  "title": "The Marital_status Schema",
  "default": "",
  "examples": [
    "Married"
  ],
  "pattern": "^(.*)$"
}
"Employer": {
  "$id": "#/properties/Employer",
  "type": "string",
  "title": "The Employer Schema",
  "default": "",
  "examples": [
    "Roivant"
  ],
  "pattern": "^(.*)$"
        }
    }
}

我的问题

我想根据提供的模式数据指定棉花糖字段。像这样:

fields.magicmethod(the_template_schema)
ContactInfo(data)

这可能吗?如果是这样,如何?

在棉花糖中,架构应该在 Python 代码中指定为类(请参阅此处的示例:https://marshmallow.readthedocs.io/en/3.0/quickstart.html#declaring-schemas)。

对于您的情况,它可能看起来像

from marshmallow import Schema, fields
class ContactInfoSchema(Schema):
    Marital_Status=Fields.Str()
    Employer=Fields.Str()

你需要使用棉花糖吗?如果您的架构已以 json 架构格式存在,则可以使用 json.load 加载对象,并使用 jsonschema 模块针对架构进行验证。

https://medium.com/python-pandemonium/json-the-python-way-91aac95d4041

https://python-jsonschema.readthedocs.io/en/latest/

您可以编写自己的转换器,该转换器将采用 JSON 模式并从中创建动态棉花糖模式。

这里有一个例子(它不是JSONSchema,而是更简单的东西)。

from marshmallow import Schema, fields
from functools import partial

def validator(valid_values, input):
    if input in valid_values:
        return True
    return False

def get_type(param_type):
    if param_type == "String":
        return fields.String
    if param_type == "Boolean":
        return fields.Boolean
def gen_schema(cls_name, params):
    fields = {}
    for p in params:
        field_type = get_type(p["type"])
        if p.get("valid_values"):
            fields[p["name"]] = field_type(validate=partial(validator, p["valid_values"]))
        else:
            fields[p["name"]] = field_type()
    schema = type(cls_name, (Schema,), fields)
    return schema
class ParameterSchema(Schema):
    name = fields.String(required=True)
    description = fields.String(required=False)
    required = fields.Bool(default=False)
    type = fields.String(required=True)
    valid_values = fields.List(fields.String, required=False)
p = [
  {"name": "filename",
   "description": "Should be a filename",
   "required": True,
   "type": "String",
   "valid_values": ["hello.txt", "foo.py", "bar.png"]
  },
  {"name": "SomeBool",
   "description": "Just a bool",
   "required": True,
   "type": "Boolean",
  },
  {"name": "NotRequiredBool",
   "description": "Another bool thats not required",
   "required": False,
   "type": "Boolean"
  }
]
req1 = {"filename": "foo.py", "SomeBool": False}
req2 = {"filename": "hi.txt", "SomeBool": True, "NotRequiredBool": False}
schema = ParameterSchema()
params1 = schema.load(p, many=True)
dynamic_schema = gen_schema("D1", params1.data)()
dynamic_res1 = dynamic_schema.load(req1)
dynamic_res2 = dynamic_schema.load(req2)
print(dynamic_res1)
print(dynamic_res2)

运行此打印:

UnmarshalResult(data={'filename': 'foo.py', 'SomeBool': False}, errors={})
UnmarshalResult(data={'NotRequiredBool': False, 'SomeBool': True}, errors={'filename': ['Invalid value.']})

您只需要更改gen_schema即可接受有效的 JSONSchema,而不是我在这里编写的简单 JSONSchema。

希望有帮助。

最新更新