2016-01-05 20 views
12

Supponiamo che sto scrivendo serializzazione personalizzata per alcune classi, ma vorrei elaborare uno dei suoi campi con metodi predefiniti.Come delegare alla deserializzazione predefinita nel deserializzatore personalizzato in Jackson?

Come fare?

Durante la serializzazione abbiamo JsonGenerator#writeObjectField().

Ma qual è il metodo corrispondente per la deserializzazione?

proposito il codice qui sotto:

import com.fasterxml.jackson.core.*; 
import com.fasterxml.jackson.databind.*; 
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 
import com.fasterxml.jackson.databind.annotation.JsonSerialize; 

import java.io.IOException; 
import java.util.Objects; 

public class TryDelegate { 

    public static class MyOuterClassSerializer extends JsonSerializer<MyOuterClass> { 

     @Override 
     public void serialize(MyOuterClass value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException { 
     gen.writeStartObject(); 

     gen.writeObjectField("inner", value.getInner()); 

     gen.writeEndObject(); 
     } 
    } 

    public static class MyOuterClassDeserializer extends JsonDeserializer<MyOuterClass> { 
     @Override 
     public MyOuterClass deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { 


     MyOuterClass ans = new MyOuterClass(); 

     JsonToken token; 

     token = p.getCurrentToken(); 
     if(token != JsonToken.START_OBJECT) { 
      throw new JsonParseException("Start object expected", p.getCurrentLocation()); 
     } 

     if(!"inner".equals(p.nextFieldName())) { 
      throw new JsonParseException("'inner; field expected", p.getCurrentLocation()); 
     } 

     MyInnerClass inner = null;// how to desrialize inner from here with default processing??? 
     ans.setInner(inner); 

     token = p.nextToken(); 
     if(token != JsonToken.END_OBJECT) { 
      throw new JsonParseException("End object expected", p.getCurrentLocation()); 
     } 

     return ans; 

     } 
    } 

    public static class MyInnerClass { 
     private int value; 

     public int getValue() { 
     return value; 
     } 

     public void setValue(int value) { 
     this.value = value; 
     } 

     @Override 
     public String toString() { 
     return "{\"value\":" + value + "}"; 
     } 
    } 

    @JsonDeserialize(using = MyOuterClassDeserializer.class) 
    @JsonSerialize(using = MyOuterClassSerializer.class) 
    public static class MyOuterClass { 

     private MyInnerClass inner; 

     public MyInnerClass getInner() { 
     return inner; 
     } 

     public void setInner(MyInnerClass inner) { 
     this.inner = inner; 
     } 

     @Override 
     public String toString() { 
     return "{\"inner\":" + Objects.toString(inner) + "}"; 
     } 
    } 

    public static void main(String[] args) throws IOException { 

     ObjectMapper mapper = new ObjectMapper(); 
     String string; 

     MyInnerClass inner = new MyInnerClass(); 
     inner.setValue(12); 

     MyOuterClass outer = new MyOuterClass(); 
     outer.setInner(inner); 

     string = mapper.writeValueAsString(outer); 
     System.out.println(string); 

     MyOuterClass outer2 = mapper.readValue(string, MyOuterClass.class); 
     System.out.println(outer2); // inner was not deserialized 


    } 
} 

Come implementare MyOuterDeserializer?

+1

forse questo può aiutare http://stackoverflow.com/questions/18313323/how-do-i-call-the-default-deserializer-from-a-custom-deserializer-in-jackson –

risposta

5

Il DeserializationContext offre questi strumenti.

Dopo aver controllato il nome del campo per "inner", passare al token successivo, l'inizio del oggetto JSON e utilizzare il DeserializationContext per deserializzare l'oggetto JSON in un oggetto MyInnerClass.

if (!"inner".equals(p.nextFieldName())) { 
    throw new JsonParseException("'inner; field expected", p.getCurrentLocation()); 
} 
p.nextToken(); // consumes the field name token 

MyInnerClass inner = ctxt.readValue(p, MyInnerClass.class); 

Gli stati javadoc

metodo

pratico che può essere utilizzato da compositi o contenitori deserializzatore, per leggere i valori una tantum contenuti (per le sequenze, ma è più efficiente per recuperare effettivamente deserializzatore volta per l'intera collezione ).


attento durante l'utilizzo del DeserializationContext. Non provare a deserializzare ricorsivamente i tipi per i quali sono stati registrati i deserializzatori personalizzati.

+0

* Non provare deserializzare ricorsivamente i tipi per i quali sono stati registrati i deserializzatori personalizzati. * In che modo applicheresti la deserializzazione predefinita in questo caso? – shmosel

+0

@shmosel Ci sono alcune soluzioni fornite [qui] (http://stackoverflow.com/questions/18313323/how-do-i-call-the-default-deserializer-from-a-custom-deserializer-in-jackson). –

Problemi correlati