2015-07-26 9 views
12

La mia struttura JSON:JsonSubTypes, elenco di oggetti polymorpic e Parcelable

{ 
    ... 
    "type":"post", // Type could vary 
    "items":[]  // Array of items, each item is typeOf("type") 
    ... 
} 

Come posso deserializzare integrante correttamente items elenco all'interno della mia POJO:

public class ItemsEnvelope { 
    private String type; 

    @JsonTypeInfo(
      use = JsonTypeInfo.Id.NAME, 
      include = JsonTypeInfo.As.EXTERNAL_PROPERTY, 
      property = "type", 
      visible = true) 
    @JsonSubTypes({ 
      @JsonSubTypes.Type(value = A.class, name = "A"), 
      @JsonSubTypes.Type(value = B.class, name = "B"), 
      @JsonSubTypes.Type(value = C.class, name = "C") 
    }) 
    private List<Item> items; 

    interface Item extends Parcelable {} 

    class A implements Item { 
     // Bunch of getters/setters and Parcelable methods/constructor 
    } 

    class B implements Item { 
     // Bunch of getters/setters and Parcelable methods/constructor 
    } 

    class C implements Item { 
     // Bunch of getters/setters and Parcelable methods/constructor 
    } 

    // Bunch of getters/setters and Parcelable methods/constructor 
} 

Per pacco elenco digitato un oggetto CREATOR dovrebbe essere fornito, che un'interfaccia, ovviamente, non può avere. Dovrei usare una classe astratta invece di interfaccia?

risposta

0

Bene, dal momento che Jackson si aspetta informazioni sul tipo su ciascun elemento dell'elenco e non volevo scrivere un deserializzatore personalizzato per questo POJO - l'ho risolto in un altro modo.

Prima di tutto ho realizzato un'interfaccia che tutti gli elementi del mio sottotipo dovevano implementare.

@JsonTypeInfo(
     use = JsonTypeInfo.Id.NAME, 
     include = JsonTypeInfo.As.EXTERNAL_PROPERTY, 
     property = "type", 
     visible = true) 
@JsonSubTypes({ 
     @JsonSubTypes.Type(value = PostFeedItem.class, name = BaseFeedItem.TYPE_POST), 
     @JsonSubTypes.Type(value = PhotoFeedItem.class, name = BaseFeedItem.TYPE_PHOTO), 
     @JsonSubTypes.Type(value = AudioFeedItem.class, name = BaseFeedItem.TYPE_AUDIO), 
     @JsonSubTypes.Type(value = VideoFeedItem.class, name = BaseFeedItem.TYPE_VIDEO), 
     @JsonSubTypes.Type(value = FriendFeedItem.class, name = BaseFeedItem.TYPE_FRIEND) 
}) 
public interface FeedItem extends Parcelable { 
    // ... 
    @BaseFeedItem.Type 
    String getType(); 
    // ... 
} 

Quindi ho creato una classe base, che ha dovuto estendere tutti gli elementi del mio sottotipo.

public abstract class BaseFeedItem implements FeedItem { 
    public static final String TYPE_POST = "post"; 
    public static final String TYPE_COMMUNITY_POST = "group_post"; 
    public static final String TYPE_PHOTO = "photo"; 
    public static final String TYPE_AUDIO = "audio"; 
    public static final String TYPE_VIDEO = "video"; 
    public static final String TYPE_FRIEND = "friend"; 

    @Retention(RetentionPolicy.SOURCE) 
    @StringDef({TYPE_POST, TYPE_COMMUNITY_POST, TYPE_PHOTO, TYPE_AUDIO, TYPE_VIDEO, TYPE_FRIEND}) 
    public @interface Type {} 
    private String type; 

    @Type 
    public String getType() { 
     return type; 
    } 
    // ... 
} 

Infine, la mia classe POJO:

public class NewsFeedEnvelope { 
    // ... 
    @JsonProperty("rows") 
    private List<FeedItem> items; 
    // ... 
} 

Ora POJO è successo deserializzata automaticamente da Jackson senza deserializzatore personalizzati.

0

Le operazioni preliminari: EXTERNAL_PROPERTY funzioneranno solo quando il valore è incluso in un altro oggetto (POJO); e non funzionerà per List s, array o Map s.

Se si utilizzava un altro metodo di inclusione, le cose dovrebbero funzionare in quanto è possibile serializzare il contenuto come JSON e leggere i tipi di conservazione posteriore JSON prodotti come previsto. Cioè, la serializzazione round-trip è supportata quando si inizia con oggetti Java. Oltre a ciò, alcune strutture di codifica JSON possono essere supportate; ma dipende dal tipo esatto di struttura che stai cercando di supportare.

+0

Aggiunta la struttura JSON alla domanda. Quale metodo di inclusione dovrei usare nel mio caso? – localhost

+0

Non c'è modo di indicare i tipi di tutti gli elementi di una matrice JSON; Jackson si aspetta informazioni sul tipo su ciascun elemento. Quindi, per supportare questo accordo, è necessario scrivere un deserializzatore personalizzato (e serializzatore se si desidera produrre tale JSON). – StaxMan

Problemi correlati