2011-12-19 33 views
98

¿Es posible: tener un campo en clase, pero diferentes nombres durante la serialización/deserialización en la biblioteca Jackson?Diferentes nombres de propiedad JSON durante serialización y deserialización

Por ejemplo, tengo la clase "Coordiantes".

class Coordinates{ 
    int red; 
} 

Para deserialización de JSON quiere tener formato de la siguiente manera:

{ 
    "red":12 
} 

Pero cuando voy a serializar objeto, resultado debe ser como este:

{ 
    "r":12 
} 

Traté de poner en práctica esto aplicando la anotación @JsonProperty tanto en getter como en setter (con diferentes valores):

class Coordiantes{ 
    int red; 

    @JsonProperty("r") 
    public byte getRed() { 
     return red; 
    } 

    @JsonProperty("red") 
    public void setRed(byte red) { 
     this.red = red; 
    } 
} 

pero tengo una excepción:

org.codehaus.jackson.map.exc.UnrecognizedPropertyException: campo no reconocido "roja"

Respuesta

130

Sólo probado y funciona esto:

public class Coordinates { 
    byte red; 

    @JsonProperty("r") 
    public byte getR() { 
     return red; 
    } 

    @JsonProperty("red") 
    public void setRed(byte red) { 
     this.red = red; 
    } 
} 

La idea es que los nombres de los métodos sean diferentes, por lo que jackson lo analiza como campos diferentes, no como un solo campo.

Aquí es el código de prueba:

Coordinates c = new Coordinates(); 
c.setRed((byte) 5); 

ObjectMapper mapper = new ObjectMapper(); 
System.out.println("Serialization: " + mapper.writeValueAsString(c)); 

Coordinates r = mapper.readValue("{\"red\":25}",Coordinates.class); 
System.out.println("Deserialization: " + r.getR()); 

Resultado:

Serialization: {"r":5} 
Deserialization: 25 
+0

es lo mismo posible con jaxb? – CuiPengFei

12

Me gustaría unir dos captadores distintos/set par a uno variables:

class Coordinates{ 
    int red; 

    @JsonProperty("red") 
    public byte getRed() { 
     return red; 
    } 

    public void setRed(byte red) { 
     this.red = red; 
    } 

    @JsonProperty("r") 
    public byte getR() { 
     return red; 
    } 

    public void setR(byte red) { 
     this.red = red; 
    } 
} 
+6

Pero en este caso, durante la serialización, obtendremos ambas propiedades: "r" y "red", con los mismos valores. – kiRach

+0

funcionó para mí, la respuesta anterior no lo hizo +1 – Tim

4

Esto no era lo que estaba esperando una solución (aunque es un caso de uso legítimo). Mi requisito era permitir que un cliente con errores existente (una aplicación móvil que ya se lanzó) use nombres alternativos.

La solución consiste en proporcionar un método de selección separada de esta manera:

@JsonSetter("r") 
public void alternateSetRed(byte red) { 
    this.red = red; 
} 
0

Usted puede escribir una clase serializar a hacer eso:

clase pública Símbolo

{ símbolo cadena privada;

private String name; 

public String getSymbol() { 
    return symbol; 
} 
public void setSymbol(String symbol) { 
    this.symbol = symbol; 
}  
public String getName() { 
    return name; 
}  
public void setName(String name) { 
    this.name = name; 
} 

}

clase pública SymbolJsonSerializer extiende JsonSerializer {

@Override 
public void serialize(Symbol symbol, JsonGenerator jgen, SerializerProvider serializers) throws IOException, JsonProcessingException { 
    jgen.writeStartObject(); 

    jgen.writeStringField("symbol", symbol.getSymbol()); 
    //Changed name to full_name as the field name of Json string 
    jgen.writeStringField("full_name", symbol.getName()); 
    jgen.writeEndObject(); 
} 

}

 ObjectMapper mapper = new ObjectMapper(); 

     SimpleModule module = new SimpleModule(); 
     module.addSerializer(Symbol.class, new SymbolJsonSerializer()); 
     mapper.registerModule(module); 

     //only convert non-null field, option... 
     mapper.setSerializationInclusion(Include.NON_NULL); 

     String jsonString = mapper.writeValueAsString(symbolList); 
1

Deben han incluido esto como una característica, porque ahora el establecimiento de un diferente @JsonProperty para una getter y setter dan como resultado exactamente lo que esperarías (nombre de propiedad diferente durante serialización y deserialización para el mismo campo). Jackson versión 2.6.7

4

Es posible tener par getter/setter normal. Sólo tiene que especificar el modo de acceso en @JsonProperty

Esto es prueba de la unidad para que:

public class JsonPropertyTest { 

    private static class TestJackson { 

    private String color; 

    @JsonProperty(value = "device_color", access = JsonProperty.Access.READ_ONLY) 
    public String getColor() { 
     return color; 
    }; 

    @JsonProperty(value = "color", access = JsonProperty.Access.WRITE_ONLY) 
    public void setColor(String color) { 
     this.color = color; 
    } 

    } 

    @Test 
    public void shouldParseWithAccessModeSpecified() throws Exception { 
    String colorJson = "{\"color\":\"red\"}"; 
    ObjectMapper mapper = new ObjectMapper(); 
    TestJackson colotObject = mapper.readValue(colorJson, TestJackson.class); 

    String ser = mapper.writeValueAsString(colotObject); 
    System.out.println("Serialized colotObject: " + ser); 
    } 
} 

me dio la salida de la siguiente manera:

Serialized colotObject: {"device_color":"red"} 
10

Puede utilizar @jsonAlias ​​que consiguió introducirse en Jackson 2.9.0

Ejemplo:

public class Info { 
    @JsonAlias({ "r", "red" }) 
    public String r; 
} 
+0

La [documentación de @JsonAlias] (http://fasterxml.github.io/jackson-annotations/javadoc/2.9.pr1/com/fasterxml/jackson/annotation/JsonAlias.html) declara explícitamente que 'no tiene ningún efecto durante serialización donde el nombre primario siempre se usa'. Esto no es lo que quiere el OP. –

0

Puede usar una combinación de @JsonSetter y @JsonGetter para controlar la deserialización y la serialización de su propiedad, respectivamente.

import com.fasterxml.jackson.annotation.JsonSetter;  
import com.fasterxml.jackson.annotation.JsonGetter; 

class Coordinates { 
    private int red; 

    //# Used during serialization 
    @JsonGetter("r") 
    public int getRed() { 
     return red; 
    } 

    //# Used during deserialization 
    @JsonSetter("red") 
    public void setRed(int red) { 
     this.red = red; 
    } 
} 
Cuestiones relacionadas