2016-05-20 9 views
8

Ich benutze Jersey, um RESTful Webservice zu implementieren. Jetzt ist der MediaType, in dem ich Daten zurückgebe, JSON.Passen Sie Jsons Serializer anstelle von Jerseys Standard an?

@GET 
@Produces({MediaType.APPLICATION_JSON }) 
public Response service() { 
    return Response 
      .ok(entity) 
      .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON) 
      .build(); 
} 

Hier stelle ich CONTENT_TYPE JSon und mein Unternehmen wird von Jersey Rahmen zu json umgewandelt werden.

Jetzt möchte ich meine JSON Antwort anpassen.

ZB: Ich möchte die leeren Elemente entfernen oder den Namen des Schlüssels meines Json-Objekts ändern. Standard Jersey Json Umwandlung:

{ 
    "cinter" : { 
    "state" : 1, 
    "checks" : 10, 
    } 
} 

Was ich will:

{ 
    "cin" : { 
    "st" : 1, 
    "cs" : 10, 
    } 
} 

Ich weiß, kann ich Jackson Bibliothek meiner eigenen ObjectMapper anpassen meine Json nach meinen Bedürfnissen verwenden.

Aber ist dies der Standard Weg, es zu tun, wenn ich JSON-Konvertierung auf eine andere Art und Weise als Jersey Standardkonvertierung möchte?

Oder kann ich paramaters in Jerseys ObjectMapper ändern?

Sollte ich meine eigene ObjectMapper verwenden?

+0

Wie sieht POJO aus? Weil es leicht mit @JsonProperty (name = "cit") und so weiter oben Feldnamen gelöst werden kann.Wenn du deinen Pojo nicht ändern kannst, dann musst du einen benutzerdefinierten Mixin oder Serializer auf deinem 'ObjectMapper' verwenden. – varren

+0

@Meine POJO hat JAXB Annotationen (@XmlRootElement) ans ja kann ich nicht ändern. Also sollte ich für jede unterschiedliche Antwort 'ObjectMapper' anders konfigurieren? Irgendeine Idee über 'ContextResolver'? –

+0

Sie können sie nicht ändern, aber können Sie Anmerkungen hinzufügen? Wenn Sie können, '@ JsonProperty' auf den Eigenschaften und' @ JsonRootName' auf der Klasse mit Ihrem Problem lösen –

Antwort

3

Hier sind meine Gedanken über Ihre Möglichkeiten. Zuerst einmal

Also für jede andere Antwort sollte ich ObjectMapper anders konfigurieren?

Wenn Sie beide json Versionen an verschiedenen Orten verwenden möchten wie diese

public Response getObject()   // returns {"cinter" : {"state" : 1,"checks" : 10}} 
public Response getShortNamesObject() // returns {"cin" : {"st" : 1,"cs" : 10}} 

als yep, müssen Sie mehrere ObjectMappers verwenden.

Aber wenn Sie nur 1 Darstellung überall verwenden möchten, dann werden Sie wahrscheinlich in der Lage sein, Jackson einmal mit benutzerdefinierten Mixin für Ihre Klassen einzurichten. Auf jeden Fall ist hier, wie Sie beide Optionen können: Und können mit nur 1 json Version auf einfachen Fall aussehen benötigt

public class TestBean { 
    private String name; 
    private int id; 
    //getters and setters 
} 

public interface TestBeanMixin { 
    @JsonProperty("short_field_name") 
    String getName(); 
    @JsonProperty("short_field_id") 
    int getId(); 
} 

@Provider 
@Priority(1) 
public class MixInJacksonJsonProvider extends JacksonJaxbJsonProvider { 
    private static final ObjectMapper mapper = createMapper(); 

    public MixInJacksonJsonProvider() { 
     setMapper(mapper); 
    } 

    private static ObjectMapper createMapper() { 
     final ObjectMapper result = new ObjectMapper(); 
     result.addMixIn(TestBean.class, TestBeanMixin.class); 
     return result; 
    } 
} 

Dieser Code wird Kurznamen produzieren für Sie Felder überall Pojo. und implementieren unterschiedliche Verhalten für unterschiedliche Anforderung müssen wir wie diese neue benutzerdefinierte Anmerkung hinzufügen:

@Retention(RetentionPolicy.RUNTIME) 
@Target({ElementType.METHOD, ElementType.TYPE}) 
public @interface MixIn {} 

-Controller wird wie folgt aussehen:

@Path("test") 
public class MyResource { 

    @GET 
    @MixIn // <== Here is important part 
    @Produces(MediaType.APPLICATION_JSON) 
    public Response getShortName() { 
     return Response.ok(demoObj()).build(); 
    } 

    @POST 
    @Produces(MediaType.APPLICATION_JSON) 
    public Response postLongName() { 
     return Response.ok(demoObj()).build(); 
    } 
} 

Und unsere MixInJacksonJsonProvider haben 2 weitere @Override:

//.. same as before 

    @Override 
    public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { 
     return super.isReadable(type, genericType, annotations, mediaType) && hasMixInAnnotation(annotations); 
    } 

    @Override 
    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { 
     return super.isWriteable(type, genericType, annotations, mediaType) && hasMixInAnnotation(annotations); 
    } 
    public static boolean hasMixInAnnotation(Annotation[] annotations){ 
     for(Annotation annotation: annotations){ 
      if (annotation instanceof MixIn){ 
       return true; 
      } 
     } 
     return false; 
    } 
} 

Hier ist Demo-Code für Sie zu spielen: https://github.com/varren/jersey2-jacksonsetup/tree/master/src/main/java/ru/varren

+0

Zusammen mit kurzen Namen, möchte ich auch andere Konfigurationen wie 'objectMapper.WRAP_ROOT_VALUE' in einigen Pojos und vielleicht nicht in Andere. Werden also alle in "ObjectMapper" bereitgestellten Konfigurationen durch Anmerkungen in MixIn-Klassen verfügbar sein? –

+0

@SiddharthTrikha es hängt wirklich davon ab, was Sie wollen. Wenn Sie möchten, dass 1 pojo die gleiche Darstellung die ganze Zeit mit WRAP_ROOT zum Beispiel und anderen pojo ohne hat, können Sie das mit nur 1 Objektmapper tun. Sie können Ihren Klassen-Serializer ändern oder Anmerkungen zu Ihrer Klasse hinzufügen oder MixIn verwenden. Es spielt wirklich keine Rolle. Wenn Sie jedoch mehrere JSON-Versionen desselben POJO benötigen, müssen Sie mehrere Objekt-Mapper erstellen und verschiedene Mixins/Serialisierer verwenden. Verwenden Sie in Ihrem Controller benutzerdefinierte Anmerkungen, um anzugeben, welche Version verwendet werden soll. – varren