2015-01-09 19 views
9

Điều tôi có:Tạo Lược đồ Json từ POJO với một twist

Tôi đang tạo một giản đồ JSON từ một pojo. Mã của tôi để tạo lược đồ trông giống như vậy:

ObjectMapper mapper = new ObjectMapper(); 
TitleSchemaFactoryWrapper visitor = new TitleSchemaFactoryWrapper(); 
mapper.acceptJsonFormatVisitor(clazz, visitor); 
JsonSchema schema = visitor.finalSchema(); 
schemas.put(clazz, mapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema)); 

Tôi đang tạo một vài lược đồ thông qua mã ở trên. Một trong những POJO có một enum nhúng nội bộ để hạn chế giá trị có thể, như vậy:

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

    } 

} 

Đoạn mã trên nên hạn chế các giá trị chuỗi có thể có trong dữ liệu JSON đó là thông qua xung quanh để "Monday", "Thứ ba", "thứ tư", vv

Khi tôi chạy máy phát điện schema trên mã trong câu hỏi, tôi hy vọng sẽ có được một cái gì đó giống như sơ đồ sau:

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

nhưng thay vào đó tôi nhận được điều này:

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

Tôi đã thực hiện một số thao tác trong mã nguồn của Mô-đun lược đồ Jackson và tìm ra điều đang xảy ra là Jackson sử dụng ".toString()" làm phương thức tuần tự mặc định cho loại enum, nhưng tôi cần nó là tạo dòng giống như thế này dựa trên StartDayOfWeek.values():

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

Có ai biết cách làm điều đó không?

+0

Có lẽ bạn muốn thử JJSchema để thay thế. – fge

+0

Cho rằng tôi nhận được một NPE khi làm theo ví dụ sử dụng của họ, thực tế là đã không có một cập nhật cho dự án trong 6 tháng và thực tế là nó vẫn còn trong trạng thái beta, tôi không nghĩ rằng đó là một lựa chọn tốt – StormeHawke

+0

Bạn có sử dụng bộ lọc deserializer tùy chỉnh để deserialize đúng (ví dụ như enum, không phải là String) ngày của giá trị tuần? – user3159253

Trả lời

2

câu trả lời Storme của tham chiếu org.codehaus, mà là một phiên bản cũ của jackson. Sau đây là tương tự nhưng sử dụng fastxml (phiên bản mới hơn).

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

} 
+1

Lưu ý rằng cả hai org.codehaus.jackson và com.fasterxml.jackson sẽ tạo phiên bản v3 của lược đồ json chứ không phải v4. Thêm chi tiết tại - https://github.com/FasterXML/jackson-module-jsonSchema/issues/9 –

11

Dường như không thể thực hiện được bằng các hướng dẫn mà tôi đã tìm thấy bằng cách sử dụng databind. Tuy nhiên tôi tìm thấy một mô-đun jackson mà dường như làm các trick độc đáo. Oddly một số các đối tượng được đặt tên giống nhau.

TLDR: sử dụng các đối tượng từ gói org.codehaus.jackson.map thay vì gói com.fasterxml.jackson.databind. Nếu bạn đang làm theo hướng dẫn trên trang this thì bạn đang làm sai. Chỉ cần sử dụng mô-đun jackson-mapper thay thế.

Dưới đây là đoạn code cho nhân viên của Google trong tương lai:

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 đại diện cho một phiên bản cũ của Jackson phải không? –

+0

Tôi nghĩ vậy. Tôi chỉ biết điều này làm việc cho tôi, nơi những nỗ lực khác không – StormeHawke

Các vấn đề liên quan