Jackson:如何生成拒绝所有其他内容的 json 架构

我想生成JSON架构,其中将应用于我拥有的所有类。"additionalProperties" : false

假设我有以下类:

class A{
    private String s;
    private B b;

    public String getS() {
        return s;
    }

    public B getB() {
        return b;
    }
}

class B{
    private BigDecimal bd;

    public BigDecimal getBd() {
        return bd;
    }
}

当我生成架构时,如下所示代码,架构属性仅适用于类。"additionalProperties" : falseA

ObjectMapper mapper = new ObjectMapper();
JsonSchemaGenerator schemaGen = new JsonSchemaGenerator(mapper);
ObjectSchema schema = schemaGen.generateSchema(A.class).asObjectSchema();
schema.rejectAdditionalProperties();
mapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema);

如何生成将应用于所有类的架构?"additionalProperties" : false

示例schema

{ "type" : "object", "id" : "urn:jsonschema:com.xxx.xxx:A", "additionalProperties" : false, "properties" : { "s" : { "type" : "string" }, "b" : { "type" : "object", "id" : "urn:jsonschema:com.xxx.xxx:B", "properties" : { "bd" : { "type" : "number" } } } } }

注意:我不想逐个生成方案。

有关信息:如果有人有兴趣,我已经打开了此方案的问题,您可以支持解决此问题。生成应拒绝所有其他内容的 json 架构


答案 1

您需要为每个属性指定架构,例如:

ObjectMapper mapper = new ObjectMapper();
JsonSchemaGenerator schemaGen = new JsonSchemaGenerator(mapper);
ObjectSchema schemaB = schemaGen.generateSchema(B.class).asObjectSchema();
schemaB.rejectAdditionalProperties();

ObjectSchema schema = schemaGen.generateSchema(A.class).asObjectSchema();
schema.rejectAdditionalProperties();
schema.putProperty("b", schemaB);

您可以利用反射 API 自动为您执行此操作。下面是一个快速而肮脏的示例:

public static void main(String[] args) throws JsonProcessingException {
    final ObjectMapper mapper = new ObjectMapper();
    final JsonSchemaGenerator schemaGen = new JsonSchemaGenerator(mapper);
    ObjectSchema schema = generateSchema(schemaGen, A.class);
    schema.rejectAdditionalProperties();
    System.out.print(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema));
}

public static <T> ObjectSchema generateSchema(JsonSchemaGenerator generator, Class<T> type) throws JsonMappingException {
    ObjectSchema schema = generator.generateSchema(type).asObjectSchema();
    for (final Field field : type.getDeclaredFields()) {
        if (!field.getType().getName().startsWith("java") && !field.getType().isPrimitive()) {
            final ObjectSchema fieldSchema = generateSchema(generator, field.getType());
            fieldSchema.rejectAdditionalProperties();
            schema.putProperty(field.getName(), fieldSchema);
        }
    }
    return schema;
}

答案 2

好吧,如果你不想使用反射,我会选择一条更简单的路线。我会使用JSONPath。因此,您需要在下面添加到您的pom.xml

  <dependency>
    <groupId>com.jayway.jsonpath</groupId>
    <artifactId>json-path</artifactId>
    <version>2.3.0</version>
  </dependency>

然后,下面的代码演示如何更改生成的 JSON 文件

package taruntest;

import com.jayway.jsonpath.*;

public class Test {

    public static void main(String[] args) throws Exception {
        String data = "{\n" +
                "  \"type\" : \"object\",\n" +
                "  \"id\" : \"urn:jsonschema:com.xxx.xxx:A\",\n" +
                "  \"additionalProperties\" : false,\n" +
                "  \"properties\" : {\n" +
                "    \"s\" : {\n" +
                "      \"type\" : \"string\"\n" +
                "    },\n" +
                "    \"b\" : {\n" +
                "      \"type\" : \"object\",\n" +
                "      \"id\" : \"urn:jsonschema:com.xxx.xxx:B\",\n" +
                "      \"properties\" : {\n" +
                "        \"bd\" : {\n" +
                "          \"type\" : \"number\"\n" +
                "        }\n" +
                "      }\n" +
                "    }\n" +
                "  }\n" +
                "}";

        DocumentContext doc = JsonPath.parse(data);
        doc.put("$..[?(@.id =~ /urn:jsonschema:.*/)]", "additionalProperties", false);
        String modified =  doc.jsonString();
        System.out.println(modified);
    }
}

运行的输出是(手动格式化)

{
  "type": "object",
  "id": "urn:jsonschema:com.xxx.xxx:A",
  "additionalProperties": false,
  "properties": {
    "s": {
      "type": "string"
    },
    "b": {
      "type": "object",
      "id": "urn:jsonschema:com.xxx.xxx:B",
      "properties": {
        "bd": {
          "type": "number"
        }
      },
      "additionalProperties": false
    }
  }
}