2015-01-10 5 views
6

के साथ एक पॉलिमॉर्फिक क्लास को क्रमबद्ध करते समय अपवाद, मैं वर्तमान में जैक्सन 1.x से जैक्सन 2.5 जेसन मैपर तक कुछ कोड माइग्रेट कर रहा हूं और एक समस्या आई है जो 1.x में नहीं थी।जेएसओएन जैक्सन - कस्टम सीरिएलाइज़र

इस सेटअप है (नीचे दिए गए कोड देखें):

  • इंटरफ़ेस IPET
  • वर्ग कुत्ते को लागू करता है IPET
  • IPET @JsonTypeInfo और @JsonSubTypes साथ टिप्पणी की जाती है
  • वर्ग मानव की संपत्ति है @JsonSerialize (= customPetSerializer.class का उपयोग करके) टाइप किया गया आईपेट टाइप करें

समस्या: यदि मैं कुत्ते के एक उदाहरण को क्रमबद्ध करता हूं तो यह अपेक्षित काम करता है (जैक्सन द्वारा जेसन स्ट्रिंग में टाइप जानकारी भी जोड़ दी जाती है)। हालांकि जब मैं मानव वर्ग का एक उदाहरण को क्रमानुसार एक अपवाद कह फेंक दिया जाता है:

com.fasterxml.jackson.databind.JsonMappingException: प्रकार आईडी निपटने प्रकार com.pet.Dog के लिए लागू नहीं किया (संदर्भ श्रृंखला के माध्यम से : com.Human [ "पालतू"])

CustomPetSerializer वर्ग (एक ब्रेकप्वाइंट का उपयोग कर परीक्षण किया यह लागू नहीं है serialize (...) विधि)।

कोड:

IPET कार्यान्वयन:

@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="type") 
@JsonSubTypes({ 
    @JsonSubTypes.Type(value=Dog.class, name="dog") 
    //,@JsonSubTypes.Type(value=Cat.class, name="cat") 
    //more subtypes here... 
}) 
public interface IPet 
{ 
    public Long getId(); 
    public String getPetMakes(); 
} 

कुत्ता कार्यान्वयन:

public class Dog implements IPet 
{ 
    @Override 
    public String getPetMakes() 
    { 
     return "Wuff!"; 
    } 

    @Override 
    public Long getId() 
    { 
     return 777L; 
    } 
} 

मानव जो एक कुत्ते का मालिक:

public class Human 
{ 
    private IPet pet = new Dog(); 

    @JsonSerialize(using=CustomPetSerializer.class) 
    public IPet getPet() 
    { 
     return pet; 
    } 
} 

CustomPetSerializer कार्यान्वयन:

public class CustomPetSerializer extends JsonSerializer<IPet> 
{ 
    @Override 
    public void serialize(IPet value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException 
    { 
     if(value != null && value.getId() != null) 
     { 
      Map<String,Object> style = new HashMap<String,Object>(); 
      style.put("age", "7"); 
      gen.writeObject(style); 
     } 
    } 
} 

JUnit परीक्षण विधि:

@Test 
public void testPet() throws JsonProcessingException 
{ 
    ObjectMapper mapper = new ObjectMapper(); 

    Human human = new Human(); 

    //works as expcected 
    String json = mapper.writeValueAsString(human.getPet()); 
    Assert.assertNotNull(json); 
    Assert.assertTrue(json.equals("{\"type\":\"dog\",\"id\":777,\"petMakes\":\"Wuff!\"}")); 

    //throws exception: Type id handling not implemented for type com.pet.Dog (through reference chain: com.Human["pet"]) 
    json = mapper.writeValueAsString(human); //exception is thrown here 
    Assert.assertNotNull(json); 
    Assert.assertTrue(json.contains("\"age\":\"7\"")); 
} 

उत्तर

12

इसके अतिरिक्त आपके आप के भीतर serializeWithType ओवरराइड करने के लिए CustomPetSerializer क्योंकि IPet बहुरूपी है की आवश्यकता होगी। यही कारण है कि serialize नहीं कहा जाता है। this related SO question देखें जो विस्तार से बताता है जब serializeWithType कहा जाता है।

@Override 
public void serializeWithType(IPet value, JsonGenerator gen, 
     SerializerProvider provider, TypeSerializer typeSer) 
     throws IOException, JsonProcessingException { 

    typeSer.writeTypePrefixForObject(value, gen); 
    serialize(value, gen, provider); // call your customized serialize method 
    typeSer.writeTypeSuffixForObject(value, gen); 
} 

जो आपके Human उदाहरण के लिए {"pet":{"type":"dog":{"age":"7"}}} प्रिंट होगा: उदाहरण के लिए, अपने serializeWithType कार्यान्वयन कुछ इस तरह लग सकता है।

+1

डिंग, डिंग, डिंग ... यह सही है! आपका बहुत बहुत धन्यवाद! –

2

जैक्सन 2.9 writeTypePrefixForObject() और writeTypeSuffixForObject() को बहिष्कृत कर दिया गया है (मुझे अस्पष्ट क्यों है)।यह नया दृष्टिकोण के तहत लगता है यह अब होगा:

@Override 
public void serializeWithType(IPet value, JsonGenerator gen, 
     SerializerProvider provider, TypeSerializer typeSer) 
     throws IOException, JsonProcessingException { 

    WritableTypeId typeId = typeSerializer.typeId(value, START_OBJECT); 
    typeSer.writeTypePrefix(gen, typeId); 
    serialize(value, gen, provider); // call your customized serialize method 
    typeSer.writeTypeSuffix(gen, typeId); 
} 

तो अब एक अतिरिक्त पंक्ति है, तो यकीन नहीं क्यों यह एक कदम आगे है, शायद यह typeId वस्तु पुन: उपयोग और अधिक कुशल है।

स्रोत: जैक्सन की ObjectNode कक्षा वर्तमान में मास्टर में है। सबसे अच्छा स्रोत नहीं है लेकिन यह बताते हुए कि क्या करना है, कोई अपग्रेड दस्तावेज़ नहीं देख सका।

संबंधित मुद्दे