【问题标题】:How to tell a JSON schema is compatible with another in Java?如何判断 JSON 模式与 Java 中的另一个模式兼容?
【发布时间】:2026-01-07 11:05:01
【问题描述】:

例如,我有一个 JSON 模式,如下所示:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "billing_address": { "$ref": "#/definitions/address" },
    "shipping_address": { "$ref": "#/definitions/address" }
  }

  "definitions": {
    "address": {
      "type": "object",
      "properties": {
        "street_address": { "type": "string" },
        "city":           { "type": "string" },
        "state":          { "type": "string" }
      }, 
      "required": ["street_address", "city", "state"]
    }
  }
}

这个模式表示一个对象有两个可变的billing_addressshipping_address,它们都是address类型,包含三个属性:street_address、citystate

现在我得到了另一个“更大”的架构:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "billing_address": { "$ref": "#/definitions/address" },
    "shipping_address": { "$ref": "#/definitions/address" },
    "new_address": { "$ref": "#/definitions/address" }
  }

  "definitions": {
    "address": {
      "type": "object",
      "properties": {
        "street_address": { "type": "string" },
        "city":           { "type": "string" },
        "state":          { "type": "string" },
        "zip_code":       { "type": "string" }
      }, 
      "required": ["street_address", "city", "state"]
    }
  }
}

如您所见,我在架构中添加了一个新属性 new_address,并且在 address 中有一个名为 zip_code 的新属性,这不是必需的属性

因此,如果我从旧的 JSON 模式创建了一个对象,它也应该可用于新的 JSON 模式。在这种情况下,我们将称新模式与旧模式兼容。 (换句话说,新模式是旧模式的扩展,但没有修改。)

问题是如何判断一个模式是否与 Java 中的另一个模式兼容?还应注意复杂的情况,例如数字字段的“最小”属性。

【问题讨论】:

  • json 是无模式的。您将必须实现自己的 json 验证器。但这不是很好......

标签: java json jsonschema


【解决方案1】:

只是测试它。在我当前的项目中,我正在编写以下合同测试:

1) 拥有 Java 域对象,我将其序列化为 JSON 并将其与引用 JSON 数据进行比较。我使用https://github.com/skyscreamer/JSONassert 比较两个 JSON 字符串。 对于参考 JSON 数据,您需要使用 'smaller schema' 对象。

2) 拥有示例 JSON 数据,我将其反序列化为我的域对象,并验证反序列化是否成功。我将反序列化结果与模型对象进行比较。对于示例 JSON 数据,您应该使用“更大的架构”对象。 此测试验证“较大架构”JSON 数据是否向后兼容您的“较小架构”域。

我在域模型的每一层都编写了这些测试——一个用于*对象,另一个用于每个非平凡的嵌套对象。这需要更多的测试代码和更多的 JSON 样本数据,但会提供更好的信心。如果发生故障,错误消息将被微调,您将确切地知道层次结构的级别被破坏(JSONAssert 错误消息可能有很多错误,并且对于深度嵌套的对象层次结构来说阅读起来并不容易)。所以这是一个权衡 * 维护测试代码和数据的时间 * 错误信息的质量

这样的测试很快——它们只需要 JSON 序列化/反序列化。

https://github.com/spring-cloud/spring-cloud-contract 将帮助您为 REST API、消息传递等编写合同测试 - 但对于简单的案例,我上面给出的过程可能已经足够好了

【讨论】:

    最近更新 更多