Создайте Json Schema из POJO с помощью твиста
Что у меня:
Я создаю схему JSON из pojo. Мой код для создания схемы выглядит следующим образом:
ObjectMapper mapper = new ObjectMapper();
TitleSchemaFactoryWrapper visitor = new TitleSchemaFactoryWrapper();
mapper.acceptJsonFormatVisitor(clazz, visitor);
JsonSchema schema = visitor.finalSchema();
schemas.put(clazz, mapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema));
Я генерирую несколько схем через указанный код. У одного из pojos есть внутренняя встроенная 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;
}
}
}
}
Приведенный выше код должен ограничивать возможные значения String в данных 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 и понял, что именно Джексон использует ".toString()" в качестве метода сериализации по умолчанию для типов перечислений, но вместо этого мне нужно это сделать строка, которая выглядит так на основе StartDayOfWeek.values()
:
"enum" : [ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" ]
Кто-нибудь знает, как это сделать?
Ответы
Ответ 1
Ответы Storme на ответ org.codehaus
, который является более старой версией jackson. Следующее похоже, но использует quickxml (более новая версия).
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);
}
}
Ответ 2
Кажется, что невозможно использовать инструкции, которые я нашел, используя привязку данных. Тем не менее, я нашел еще один модуль Jackson, который, похоже, прекрасно справляется с этим. Как ни странно, несколько объектов называются одинаковыми.
TL;DR: используйте объекты из пакета org.codehaus.jackson.map
, а не пакета com.fasterxml.jackson.databind
. Если вы следуете инструкциям на странице this, вы делаете это неправильно. Просто используйте модуль jackson-mapper.
Здесь код для будущих 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);
}
Ответ 3
Если кто-то приходит сюда и хочет поддержать новейшую черновую версию в своем коде.
Ищите здесь предпочитаемый язык: https://json-schema.org/implementations.html