2016-09-01 23 views
5

Ben ettik böyle DTO sınıfları: ProjemdeJSON jenerik toplama deserialization

public class AnswersDto { 
    private String uuid; 
    private Set<AnswerDto> answers; 
} 

public class AnswerDto<T> { 
    private String uuid; 
    private AnswerType type; 
    private T value; 
} 

class LocationAnswerDto extends AnswerDto<Location> { 
} 

class JobTitleAnswerDto extends AnswerDto<JobTitle> { 
} 

public enum AnswerType { 
    LOCATION, 
    JOB_TITLE, 
} 

class Location { 
    String text; 
    String placeId; 
} 

class JobTitle { 
    String id; 
    String name; 
} 

serileştirme ve JSONs ait seri kaldırma için kullanılan Jackson kütüphane bulunmaktadır.

düzgün örneğin kendi vücudunda AnswersDto ile isteği serisini mümkün olduğu AnswersDto (özel ek açıklamaları kullanın) veya AnswerDto (ek açıklama yanı) sınıfları nasıl yapılandırılır:

{ 
    "uuid": "e82544ac-1cc7-4dbb-bd1d-bdbfe33dee73", 
    "answers": [ 
     { 
      "uuid": "e82544ac-1cc7-4dbb-bd1d-bdbfe33dee73", 
      "type": "LOCATION", 
      "value": { 
       "text": "Dublin", 
       "placeId": "121" 
      } 
     }, 
     { 
      "uuid": "e82544ac-1cc7-4dbb-bd1d-bdbfe33dee73", 
      "type": "JOB_TITLE", 
      "value": { 
       "id": "1", 
       "name": "Developer" 
      } 
     } 
    ] 
} 

Maalesef Jackson varsayılan haritaları değeriyle AnswerDto nesnesinin (Location veya JobTitle) sınıf nesnesi yerine LinkedHashMap nesnesine nesne. Özel JsonDeserializer<AnswerDto> veya @JsonTypeInfo ve @JsonSubTypes kullanımı ile yapılandırma yazabilir miyim?

düzgün kullanıyorum

{ 
    "uuid": "e82544ac-1cc7-4dbb-bd1d-bdbfe33dee73", 
    "type": "LOCATION", 
    "value": { 
     "text": "Dublin", 
     "placeId": "121" 
    } 
} 

şeklinde sadece bir AnswerDto ile isteği serisini için:

AnswerDto<Location> answerDto = objectMapper.readValue(jsonRequest, new TypeReference<AnswerDto<Location>>() { 
}); 

diğer tüm özel yapılandırma olmadan.

+0

Sen aswer nesnelerinin bir koleksiyonu var ama tek bir cevap nesnesine serisini istiyor? AnswersDto yanıtlarını kullanma = objectMapper.readValue (jsonRequest, new TypeReference () {}); – reos

+0

Tüm cevapları 'cevaplar düğümden 'Set ' koleksiyonuna eşlemek istiyorum. 'objectReference ' ile 'objectMapper' kullanıldığında, koleksiyondaki her' AnswerDto'nun 'value' özelliği maalesef' LinkedHashMap' ile eşleştirilir. – Bananan

cevap

5

Ben @JsonTypeInfo ve @JsonSubTypes Jackson'un özel ek açıklamaları kullanarak sorunu çözdükten:

public class AnswerDto<T> { 

    private String uuid; 

    private AnswerType type; 

    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type") 
    @JsonSubTypes({ 
      @JsonSubTypes.Type(value = Location.class, name = AnswerType.Types.LOCATION), 
      @JsonSubTypes.Type(value = JobTitle.class, name = AnswerType.Types.JOB_TITLE) 
    }) 
    private T value; 
} 
1

Benim önerim, olası yanıt değerleri için ayrı bir arabirim yapmak ve üzerinde @JsonTypeInfo kullanın. type alanını AnswerDto, AnswerType enum'dan bırakabilir ve ek *AnswerDto sınıfları için izinli jackson sizin için tip bilgisi ekler. Bu

public class AnswerDto<T extends AnswerValue> { 
    private String uuid; 
    private T value; 
} 

@JsonTypeInfo(use = Id.CLASS, include = As.PROPERTY) 
interface AnswerValue {} 

class Location implements AnswerValue { /*..*/ } 
class JobTitle implements AnswerValue { /*..*/ } 

Ortaya json irade

AnswersDto answersDto = objectMapper.readValue(json, AnswersDto.class); 

kullanılarak ayrıştırılır bu

{ 
    "uuid": "e82544ac-1cc7-4dbb-bd1d-bdbfe33dee73", 
    "answers": [ 
    { 
     "uuid": "e82544ac-1cc7-4dbb-bd1d-bdbfe33dee73", 
     "value": { 
     "@class": "com.demo.Location", 
     "text": "Dublin", 
     "placeId": "121" 
     } 
    }, 
    { 
     "uuid": "e82544ac-1cc7-4dbb-bd1d-bdbfe33dee73", 
     "value": { 
     "@class": "com.demo.JobTitle", 
     "id": "1", 
     "name": "Developer" 
     } 
    } 
    ] 
} 

benziyor Ama json veri yapımcı olduğunda bu çözüm durumlarda geçerlidir gibi ve geriye dönük uyumluluk hakkında düşünmek zorunda değilsiniz.

Diğer durumlarda, AnswersDto sınıfı için özel desetializer yapmanız gerekir.