我经历过 XML+SOAP 的时代,曾经写过很多 xml document + xslt 的代码,也为自己的 emacs 写过一些 xml 的扩展。
对于大部分模型简单,变化快速的业务来说,json 的出现是一种进步,json 更简单,更适合阅读,可以很自然的适配常用编程语言的内置机制。
相对于各种?json 库的性能优化之争,json 的结构校验就比较少被关注了。但是对于应用业务,其实校验是非常重要的。我过去经历过的几个项目,基于不同的技术栈和演进路线,采用的 json schema 校验工具也各不相同。CSDN AI组目前使用的是 python 的 jsonschema 库 jsonschema · PyPI?。
这个库基于 json schema?
JSON Schema | The home of JSON Schema?
设计,充分利用了平台中立的规范,但是校验使用的参数是 python 数据结构。这是一个非常好的设计,首先 json schema 规范不依赖于具体的应用语言,这部分知识可以复用到各个不同的技术栈,这就确保了异构平台之间的沟通。比如 CSDN 内部就有基于 Java 和 Python 等不同语言的服务,只要遵循 json schema,就可以比较顺利的理解接口规范。而内部使用 python 数据结构,给开发带来了很大的便利。
因为历史原因,我们的一组 API 中有一个文档类型,存在两种不同的结构:
{
"sample_id": "string",
"title": "string",
"body": "string"
}
和
{
"article_id": "integer",
"title": "string",
"content": "string"
}
这其中 body 和 content 其实是同一个字段,sample_id 和 article_id 也一样,并且 article_id 其实就是整数,它在数据库中保存的也是整数。真实的情况比这两个定义更复杂一些,例如有一些接受?sample_id 的 API 其实接受整数,有一些接受 article_id 的 API 要求字符串。
程序层面处理这些差异其实不算特别难,写个简单的适配函数即可,但是在规范层面,除非在将来的升级维护中重写一组规范的 API,把这两种形式统一,否则这个差异很难消灭,它们已经被几个不同的团队使用,在不破坏其他部门的调用代码的情况下,无缝升级 API 不太现实。如果这部分 API 根据每种 case 都写一个 json schema,或者放弃这部分api的schema校验,无疑为将来的代码维护留下了隐患。
好在 json schema 为这种问题也提供了解决方案。 json schema 允许我们使用 oneOf 选择器组合多个定义,JSON数据满足其中某一个即可,再结合对字段类型的多类型定义,最终我们的项目代码中,这个schema如下:
self.article_schema = {
"properties": {
"sample_id": {
"type": ["string", "integer"]
},
"article_id": {
"type": ["string", "integer"]
},
"title": {"type": "string"},
"body": {"type": "string"},
"content": {"type": "string"}
},
"oneOf": [
{
"required": [
"title",
"body"
]
},
{
"required": [
"title",
"content"
]
}
]
}
这里面包含了对不同类型的文档 id 的支持,确保不同结构的文档约束在同一个框架下。
JSON Schema 还定义了 anyOf 和更复杂的一些条件选择器,具体的信息可以查询官方文档。
|