从POJO中生成一个带有twist的Json模式。

时间:2023-01-12 18:05:40

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有一个内嵌的enum,用于限制可能的值,如下所示:

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 Jackson Schema Module source code and figured out that what's happening is Jackson'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():

我在Jackson Schema模块源代码中做了一些挖掘,发现Jackson使用了“.toString()”作为enum类型的默认序列化方法,但是我需要它来做的是根据StartDayOfWeek.values()创建这样的行:

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

Does anyone know how to do that?

有人知道怎么做吗?

2 个解决方案

#1


3  

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

org Storme的回答引用。codehaus是杰克逊的旧版。下面是类似的,但是使用fasterxml(较新版本)。

Pom:

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>

Code:

代码:

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);
    }

}

#2


14  

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

使用databind找到的说明似乎是不可能的。然而,我发现了另一个jackson模块,它似乎很好地完成了这个任务。奇怪的是,有几个对象被命名为相同的。

TLDR: use objects from the org.codehaus.jackson.map package rather than the com.fasterxml.jackson.databind package. If you're following the instructions on this page then you're doing it wrong. Just use the jackson-mapper module instead.

使用来自org.codehaus.jackson的对象。映射包而不是com.fasterxml.jackson。databind包。如果你按照本页上的说明做,那么你做错了。只需使用jackson-mapper模块即可。

Here's the code for future googlers:

以下是未来谷歌员工的守则:

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);
}

#1


3  

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

org Storme的回答引用。codehaus是杰克逊的旧版。下面是类似的,但是使用fasterxml(较新版本)。

Pom:

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>

Code:

代码:

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);
    }

}

#2


14  

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

使用databind找到的说明似乎是不可能的。然而,我发现了另一个jackson模块,它似乎很好地完成了这个任务。奇怪的是,有几个对象被命名为相同的。

TLDR: use objects from the org.codehaus.jackson.map package rather than the com.fasterxml.jackson.databind package. If you're following the instructions on this page then you're doing it wrong. Just use the jackson-mapper module instead.

使用来自org.codehaus.jackson的对象。映射包而不是com.fasterxml.jackson。databind包。如果你按照本页上的说明做,那么你做错了。只需使用jackson-mapper模块即可。

Here's the code for future googlers:

以下是未来谷歌员工的守则:

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);
}