2015-01-09 79 views
9

我有:从POJO生成JSON Schema

我从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" 
    } 
    } 
} 

我已经在杰克逊模式模块源代码中做了一些挖掘,发现发生了什么是杰克逊使用“.toString()”作为枚举类型的默认序列化方法,但是我需要它做什么为创建一个基于StartDayOfWeek.values()看起来像这样的行:

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

有谁知道该怎么做?

+0

也许你想尝试JJSchema代替。 – fge

+0

鉴于我在使用NPE的时候得到了一个N​​PE,事实上在6个月内没有对该项目进行更新,而且事实上它仍然显然处于测试状态,所以我不认为这是一个非常不错的选择 – StormeHawke

+0

您是否已经使用自定义的反序列化器正确反序列化(例如,作为枚举,而不是字符串)星期值? – user3159253

回答

2

暴风雨的回答引用org.codehaus,这是杰克逊的旧版本。以下是类似的,但使用fasterxml(较新版本)。

双响炮:

<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将生成v3版本的json模式,而不是v4。更多详情,请访问 - https://github.com/FasterXML/jackson-module-jsonSchema/issues/9 –

11

它似乎不可能使用我发现使用数据绑定的说明。不过,我发现另一个杰克逊模块似乎很好地做了这个技巧。奇怪的几个对象被命名为相同的。

TLDR:使用来自org.codehaus.jackson.map包而非com.fasterxml.jackson.databind包的对象。如果你按照this页面上的说明,那么你做错了。只需使用jackson-mapper模块。

下面是未来的Google代码:

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

codehaus代表旧版本的杰克逊不是吗? –

+0

我这么认为。我只知道这适用于我,其他尝试没有 – StormeHawke