【问题标题】:Generate Json Schema from POJO with a twist从 POJO 生成 Json Schema
【发布时间】:2015-03-07 23:00:22
【问题描述】:

我有什么:

我正在从 pojo 生成 JSON 模式。我生成架构的代码如下所示:

ObjectMapper mapper = new ObjectMapper();
TitleSchemaFactoryWrapper visitor = new TitleSchemaFactoryWrapper();
mapper.acceptJsonFormatVisitor(clazz, visitor);
JsonSchema schema = visitor.finalSchema();
schemas.put(clazz, mapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema));

我通过上面的代码生成了几个模式。其中一个 pojo 有一个内部嵌入的枚举来限制可能的值,如下所示:

public class MyClass {

    @JsonProperty("name")
    private String name;
    @JsonProperty("startDayOfWeek")
    private MyClass.StartDayOfWeek startDayOfWeek;
    /**
     * The ID of a timezone returned by the timezones route.
     * 
     */
    @JsonProperty("timezone")
    private String timezone;
    @JsonIgnore
    private Map<String, Object> additionalProperties = new HashMap<String, Object>();

    /**
     * 
     * @return
     *     The startDayOfWeek
     */
    @JsonProperty("startDayOfWeek")
    public MyClass.StartDayOfWeek getStartDayOfWeek() {
        return startDayOfWeek;
    }

    /**
     * 
     * @param startDayOfWeek
     *     The startDayOfWeek
     */
    @JsonProperty("startDayOfWeek")
    public void setStartDayOfWeek(MyClass.StartDayOfWeek startDayOfWeek) {
        this.startDayOfWeek = startDayOfWeek;
    }

    public static enum StartDayOfWeek {

        MONDAY("Monday"),
        TUESDAY("Tuesday"),
        WEDNESDAY("Wednesday"),
        THURSDAY("Thursday"),
        FRIDAY("Friday"),
        SATURDAY("Saturday"),
        SUNDAY("Sunday");
        private final String value;
        private static Map<String, MyClass.StartDayOfWeek> constants = new HashMap<String, MyClass.StartDayOfWeek>();

        static {
            for (MyClass.StartDayOfWeek c: values()) {
                constants.put(c.value, c);
            }
        }

        private StartDayOfWeek(String value) {
            this.value = value;
        }

        @JsonValue
        @Override
        public String toString() {
            return this.value;
        }

        @JsonCreator
        public static MyClass.StartDayOfWeek fromValue(String value) {
            MyClass.StartDayOfWeek constant = constants.get(value);
            if (constant == null) {
                throw new IllegalArgumentException(value);
            } else {
                return constant;
            }
        }

    }

}

上述代码应将 JSON 数据中可能的字符串值限制为“星期一”、“星期二”、“星期三”等。

当我在相关代码上运行架构生成器时,我希望得到类似于以下架构的内容:

{
  "type" : "object",
  "javaType" : "my.package.MyClass",
  "properties": {
    "startDayOfWeek" : {
      "type" : "string",
      "enum" : [ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" ]
    }
  }
}

但我却得到了这个:

{
  "type" : "object",
  "id" : "urn:jsonschema:my:package:MyClass",
  "title" : "Lmy/package/MyClass;",
  "properties" : {
    "startDayOfWeek" : {
      "type" : "string"
    }
  }
}

我在 Jackson Schema Module 源代码中进行了一些挖掘,发现发生的事情是 Jackson 使用“.toString()”作为枚举类型的默认序列化方法,但我需要它做的是创建基于StartDayOfWeek.values() 的行看起来像这样:

"enum" : [ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" ]

有人知道怎么做吗?

【问题讨论】:

  • 也许你想试试 JJSchema。
  • 鉴于我在遵循他们的使用示例时获得了 NPE,事实上该项目在 6 个月内没有更新,而且它显然仍处于 beta 状态,我不要认为这是一个很好的选择
  • 您是否已经使用自定义反序列化器来正确反序列化(即作为枚举,而不是作为字符串)星期几的值?
  • 是的,Spring 为我们处理了所有这些

标签: java json enums jackson jackson-modules


【解决方案1】:

使用我使用数据绑定找到的指令似乎是不可能的。然而,我发现另一个杰克逊模块似乎做得很好。奇怪的是,其中几个对象的名称相同。

TLDR:使用来自org.codehaus.jackson.map 包而不是com.fasterxml.jackson.databind 包的对象。如果您按照this 页面上的说明进行操作,那么您做错了。只需使用 jackson-mapper 模块即可。

这是未来谷歌员工的代码:

private static String getJsonSchema(Class clazz) throws IOException {
    org.codehaus.jackson.map.ObjectMapper mapper = new ObjectMapper();
    //There are other configuration options you can set.  This is the one I needed.
    mapper.configure(SerializationConfig.Feature.WRITE_ENUMS_USING_TO_STRING, true);

    JsonSchema schema = mapper.generateJsonSchema(clazz);

    return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema);
}

【讨论】:

  • codehaus 代表的是旧版本的 Jackson 不是吗?
  • 我想是的。我只知道这对我有用,而其他尝试没有
【解决方案2】:

Storme 的回答参考了org.codehaus,这是杰克逊的旧版本。以下类似但使用fasterxml(较新版本)。

Pom:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.7.1</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.7.1</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.7.1</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.module</groupId>
    <artifactId>jackson-module-jsonSchema</artifactId>
    <version>2.1.0</version>
</dependency>

代码:

import ...TargetClass;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsonschema.JsonSchema;

import java.io.IOException;

public final class JsonSchemaGenerator {

    private JsonSchemaGenerator() { };

    public static void main(String[] args) throws IOException {
        System.out.println(JsonSchemaGenerator.getJsonSchema(TargetClass.class));
    }

    public static String getJsonSchema(Class clazz) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true);
        JsonSchema schema = mapper.generateJsonSchema(clazz);
        return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema);
    }

}

【讨论】:

【解决方案3】:

如果有人来到这里并想在他的代码中支持最新的草稿版本。

在此处查找您的首选语言: https://json-schema.org/implementations.html

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-23
    • 1970-01-01
    • 2019-06-23
    • 1970-01-01
    • 2014-01-17
    • 1970-01-01
    • 1970-01-01
    • 2014-03-20
    相关资源
    最近更新 更多