2015-01-09 4 views
9

Что у меня есть:Создание 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 имеет внутренний встроенный перечисление, чтобы ограничить возможные значения, например, так:

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 и выяснил, что происходит то, что Джексон использует «.toString()» в качестве метода сериализации по умолчанию для типов перечислений, но вместо этого мне нужно это делать это создать строку, которая выглядит следующим образом, основываясь на StartDayOfWeek.values():

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

кто-нибудь знает, как это сделать?

+0

Может быть, вы хотите попробовать JJSchema вместо этого. – fge

+0

Учитывая, что я получаю NPE, следуя примеру использования, тот факт, что в течение 6 месяцев не было обновления для проекта и факта, что он все еще, по-видимому, находится в состоянии бета-тестирования, я не думаю, что это очень Хороший вариант – StormeHawke

+0

Вы используете пользовательский десериализатор для правильной десериализации (т. е. как enum, а не как String) дней недельных значений? – user3159253

ответ

2

ответа Storme в ссылках org.codehaus, что старая версия Джексона. Следующее похоже, но использует 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); 
    } 

} 
+1

Обратите внимание, что оба org.codehaus.jackson и com.fasterxml.jackson будут генерировать версию json-схемы v3, а не v4. Более подробная информация - https://github.com/FasterXML/jackson-module-jsonSchema/issues/9 –

11

Кажется, что это невозможно, используя инструкции, которые я нашел, используя привязку данных. Тем не менее, я нашел еще один модуль Jackson, который, похоже, прекрасно справляется с этим. Как ни странно, несколько объектов называются одинаковыми.

TLDR: использовать объекты из пакета 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); 
} 
+1

Кодхаус представляет собой более старую версию Джексона, не так ли? –

+0

думаю. Я просто знаю, что это сработало для меня, когда другие попытки не были – StormeHawke