2016-06-03 6 views
3

Ich entwickle gerade eine kleine Webanwendung mit Dropwizard. Eine andere Anwendung kann mehrere Nachrichtentypen an meine Anwendung senden. Diese Nachrichten haben eine gemeinsame Basis und einen bestimmten Inhalt, abhängig vom Typ der Nachricht. HierWie ein Objekt mit einem generischen Typ mit einem Builder Jackson deserialisieren?

ist die gemeinsame Basis der Nachrichten:

@JsonDeserialize(builder = BaseMessageBuilder.class) 
public abstract class BaseMessage<T> { 
    private String commonFiled; 
    private T content; 

    protected BaseMessage(BaseMessageBuilder<T> builder) { 
     this.commonFiled = builder.getCommonField(); 
     this.content = builder.getContent(); 
    } 

    public String getCommonField() { 
     return commonFiled; 
    } 

    public T getContent() { 
     return content; 
    } 
} 

Hier ist der Erbauer der gemeinsamen Basis der Nachrichten:

@JsonPOJOBuilder 
public class BaseMessageBuilder<T> { 
    private String commonFiled; 
    private T content; 

    public String getCommonField() { 
     return commonFiled; 
    } 

    public BaseMessageBuilder<T> withCommonField(String commonFiled) { 
     this.commonFiled = commonFiled; 
     return this; 
    } 

    public String getContent { 
     return participants; 
    } 

    public BaseMessageBuilder<T> withContent(T content) { 
     this.content = content; 
     return this; 
    } 

    public BaseMessage<T> build() { 
     return new BaseMessage<T>(this); 
    } 
} 

Hier ist ein spezifischer Inhalt:

@JsonDeserialize(builder = SpecificContentBuilder.class) 
public abstract class SpecificContent{ 
    private String field1; 
    private Long field2; 

    protected SpecificContent(SpecificMessageBuilder builder) { 
     this.field1 = builder.getField1(); 
     this.field2 = builder.getField2(); 
    } 

    public String getField1() { 
     return field1; 
    } 

    public Long getField2() { 
     return field2; 
    } 
} 

Hier ist der Erbauer eines spezifischen Inhalts:

@JsonPOJOBuilder 
public class SpecificContentBuilder { 
    private String field1; 
    private Long field2; 

    public String getField1() { 
     return commonFiled; 
    } 

    public SpecificContentBuilder withField1(String field1) { 
     this.field1 = field1; 
     return this; 
    } 

    public String getField2 { 
     return field2; 
    } 

    public SpecificContentBuilder withField2(Long field2) { 
     this.field2 = field2; 
     return this; 
    } 

    public BaseMessage build() { 
     return new BaseMessage<T>(this); 
    } 
} 

Und hier ist meine Ressource:

@Path("/test") 
@Produces(MediaType.APPLICATION_JSON) 
@Consumes(MediaType.APPLICATION_JSON) 
public class TestResource { 

    @POST 
    public void test(BaseMessage<SpecificContent> message) { 
     // ... 
    } 

} 

Zur Zeit, als meine Ressource um das Objekt zu gewährleisten, darf der Inhalt Nachricht tatsächlich nicht die richtige Art bekommen. Wenn ich es debugge, ist es automatisch ein . Ich denke, da stimmt etwas nicht. Kann mir jemand helfen ?

EDIT:

Es ist ein Jackson Ausgabe (bei pandaadb Antwort Schauen). Ich habe meinen BaseMessageBuilder gelöscht und einen statischen Konstruktor verwendet, um mein Objekt unveränderbar zu halten.

public abstract class BaseMessage<T> { 
    private String commonFiled; 
    private T content; 

    @JsonCreator 
    public static <T> BaseMessage<T> newInstance(
      @JsonProperty("commonFiled") String commonFiled, 
      @JsonProperty("content") T content) { 
     return new WebhookEventBuilder() 
       .withCommonFied(commonFiled) 
       .withContent(content) 
       .build(); 
    } 

    protected BaseMessage(BaseMessageBuilder<T> builder) { 
     this.commonFiled = builder.getCommonField(); 
     this.content = builder.getContent(); 
    } 

    public String getCommonField() { 
     return commonFiled; 
    } 

    public T getContent() { 
     return content; 
    } 

    private static class BaseMessageBuilder<T> { 
     private String commonFiled; 
     private T content; 

     public WebhookEventType getCommonFiled() { 
      return commonFiled; 
     } 

     public BaseMessageBuilder withCommonFiled(String commonFiled) { 
      this.commonFiled = commonFiled; 
      return this; 
     } 

     public T getContent() { 
      return content; 
     } 

     public BaseMessageBuilder withContent(T content) { 
      this.content = content; 
      return this; 
     } 

     public BaseMessage build() { 
      return new BaseMessage(this); 
     } 
    } 
} 

Antwort

1

dies versucht, dies wird derzeit nicht unterstützt es scheint:

https://github.com/FasterXML/jackson-databind/issues/921

für Ihr Beispiel jedoch, dies nicht notwendig ist. Jackson das Richtige tut standardmäßig beispielsweise funktioniert das Codebeispiel für mich:

Ich habe 1 BaseMessage:

public class BaseMessage<T> { 

    @JsonProperty("val1") 
    String val1; 
    @JsonProperty("val2") 
    T val2; 
} 

und 2 verschiedene Inhaltstypen:

public class Content { 

    @JsonProperty("val1") 
    String val1; 
    @JsonProperty("val2") 
    long val2; 

} 

public class Content2 { 

    @JsonProperty("val1") 
    String val1; 
    @JsonProperty("val2") 
    String val2; 

} 

Mit dieser Ressource :

Mit den Test-URLs erkennt jackson erfolgreich den Typ T des ba se content und erstellt die richtige Instanz.

Die andere Alternative wäre eine eigene MessageBodyReader für den BaseMessage Typ

ich schreiben hoffe, dass hilft,

Artur

+0

Vielen Dank für Ihre Antwort @pandaadb. Ich fürchte, ich muss einen Trick finden. Ich möchte meinen Erbauer behalten, um unveränderliches Objekt zu haben. Ich werde versuchen, meinen eigenen Deserializer zu erstellen. –

+1

@ThomasBetous hast du in Schöpfer gesucht? Sie funktionieren gut und sehen sehr ähnlich aus. das könnte Ihre Abhilfe sein – pandaadb

+0

Ja, es hilft mir. Vielen Dank ! Sie können meine Lösung in Bearbeitung finden. –

Verwandte Themen