java 稍微从 POJO 生成 Json Schema

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27863689/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 12:32:57  来源:igfitidea点击:

Generate Json Schema from POJO with a twist

javajsonenumsHymansonHymanson-modules

提问by StormeHawke

What I have:

我有的:

I'm generating a JSON schema from a pojo. My code to generate the schema looks like so:

我正在从 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));

I'm generating several schemas via the above code. One of the pojos has an internal embedded enum to limit the possible values, like so:

我通过上面的代码生成了几个模式。其中一个 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;
            }
        }

    }

}

The above code should limit the possible String values in the JSON data that's passed around to "Monday", "Tuesday", "Wednesday", etc.

上面的代码应该限制传递给“星期一”、“星期二”、“星期三”等的 JSON 数据中可能的字符串值。

When I run the schema generator on the code in question, I expect to get something like the following schema:

当我在有问题的代码上运行模式生成器时,我希望得到类似于以下模式的内容:

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

but instead I'm getting this:

但相反,我得到了这个:

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

I've done some digging in the Hymanson Schema Module source code and figured out that what's happening is Hymanson's using ".toString()" as the default serialization method for enum types, but what I need it to do instead is create the line that looks like this based on StartDayOfWeek.values():

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

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

Does anyone know how to do that?

有谁知道这是怎么做到的吗?

采纳答案by James Oravec

Storme's answer references org.codehaus, which is an older version of Hymanson. The following is similar but uses fasterxml (newer version).

Storme 的答案参考org.codehaus,这是 Hymanson 的旧版本。以下内容类似,但使用了fasterxml(较新版本)。

Pom:

波姆:

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

Code:

代码:

import ...TargetClass;
import com.fasterxml.Hymanson.databind.ObjectMapper;
import com.fasterxml.Hymanson.databind.SerializationFeature;
import com.fasterxml.Hymanson.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);
    }

}

回答by StormeHawke

It seems to not be possible using the instructions I found using databind. However I found another Hymanson module that seems to do the trick nicely. Oddly several of the objects are named the same.

使用我使用数据绑定找到的说明似乎无法使用。但是我发现了另一个 Hymanson 模块,它似乎很好地解决了这个问题。奇怪的是,有几个对象的名称相同。

TLDR: use objects from the org.codehaus.Hymanson.mappackage rather than the com.fasterxml.Hymanson.databindpackage. If you're following the instructions on thispage then you're doing it wrong. Just use the Hymanson-mapper module instead.

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

Here's the code for future googlers:

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

private static String getJsonSchema(Class clazz) throws IOException {
    org.codehaus.Hymanson.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);
}

回答by rufreakde

If someone comes here and wants to support the newest draft version in his code.

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

Look here for your preferred language: https://json-schema.org/implementations.html

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