2015-01-09 11 views
9

Was ich habe:Generiere Json Schema von POJO mit einer Drehung

Ich erzeuge ein JSON-Schema von einem pojo. Mein Code zum Generieren des Schemas sieht so aus:

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

Ich erstelle mehrere Schemas über den obigen Code. Einer der POJOs verfügt über einen internen eingebettet Enum die möglichen Werte zu begrenzen, etwa so:

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

    } 

} 

Der obige Code sollte die möglichen String-Werte in den JSON-Daten begrenzen, um zu „Montag“ übergeben wird, „Dienstag“, „mittwoch“ usw.

Wenn ich das Schema Generator auf dem betreffenden Code ausführen, erwarte ich, dass etwas wie das folgende Schema erhalten:

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

sondern das ich erhalte:

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

Ich habe etwas im Quellcode des Jackson-Schema-Moduls gegraben und herausgefunden, dass Jacksons ".toString()" als Standard-Serialisierungsmethode für Aufzählungstypen verwendet, aber was ich stattdessen tun muss ist die Linie erstellen, die auf StartDayOfWeek.values() wie diese Basis aussieht:

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

Wer weiß, wie das zu tun?

+0

Vielleicht möchten Sie JJSchema anstatt versuchen. – fge

+0

Given, dass ich eine NPE bekommen, wenn ihre Anwendungsbeispiel folgen, dass die Tatsache, hat es kein Update auf das Projekt in 6 Monaten und die Tatsache, dass es in einem Beta-Stadium noch offensichtlich ist, ich glaube nicht, das ist ein sehr Gute Option – StormeHawke

+0

Verwenden Sie bereits einen benutzerdefinierten Deserializer, um Wochentagewerte richtig zu deserialisieren (dh als Enum, nicht als String)? Ja – user3159253

Antwort

2

Storme Antwort verweist org.codehaus, die eine ältere Version von jackson ist. Folgendes ist ähnlich, verwendet aber fasterxml (neuere Version).

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

Beachten Sie, dass beide org.codehaus.jackson und com.fasterxml.jackson werden v3-version von json schema und nicht v4 generieren. Weitere Details unter - https://github.com/FasterXML/jackson-module-jsonSchema/issues/9 –

11

Es scheint nicht möglich zu sein, die Anweisungen unter Verwendung von I mit databind gefunden. Ich fand jedoch ein anderes Jackson-Modul, das den Trick gut zu machen scheint. Seltsamerweise werden mehrere Objekte gleich benannt.

TLDR: Verwenden Sie Objekte aus dem org.codehaus.jackson.map-Paket anstelle des com.fasterxml.jackson.databind-Pakets. Wenn Sie die Anweisungen auf this Seite befolgen, dann tun Sie es falsch. Verwenden Sie stattdessen das jackson-mapper-Modul.

Hier ist der Code für die Zukunft Googler:

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 stellt eine ältere Version von Jackson, nicht wahr? –

+0

Ich denke schon. Ich weiß nur, dass das für mich funktionierte, wo andere Versuche nicht – StormeHawke