2011-06-14 24 views
44

Estoy intentando deserializar un objeto JSON almacenado en CouchDb utilizando Jackson. Este objeto necesita deserializarse en un pojo que contenga métodos sobrecargados. Cuando intento para recuperar el objeto del sofá y hacer la deserialización consigo la siguiente excepción:Deserialización de JSON en objetos con métodos sobrecargados con Jackson

org.ektorp.DbAccessException: org.codehaus.jackson.map.JsonMappingException: en conflicto definiciones setter para propiedad " multiplicador ": com.db.commodities.framework.sdos.model.security.EqOpt # setMultiplier (1 params) vs com.db.commodities.framework.sdos.model.security.EqOpt # setMultiplier (1 params)

Traté de una nnote el setter que me gustaría que Jackson use, pero parece que no funcionó.

@JsonProperty("multiplier") 
public void setMultiplier(SDOSAttribute multiplier) { 
    this.multiplier = multiplier; 
} 

public void setMultiplier(double multiplier) { 
    this.multiplier.setValue(String.valueOf(multiplier)); 
} 

¿Cómo configuro Jackson para deserializar correctamente utilizando un método específico? ¿O me estoy acercando a este problema de la manera incorrecta?

EDIT:

he realizado los siguientes cambios. Esto parece funcionar, pero es un poco más feo. Si alguien tiene una mejor manera de hacerlo, siéntete libre de compartir y con mucho gusto lo aceptaré.

@JsonProperty("multiplier") 
protected void setMultiplierAttribute(SDOSAttribute multiplier) { 
    this.multiplier = multiplier; 
} 

@JsonIgnore 
public void setMultiplier(double multiplier) { 
    this.multiplier.setValue(String.valueOf(multiplier)); 
} 
+0

Sí, esto es punto válido. Estoy de acuerdo en que sería bueno si se utilizara la inferencia de manera que si solo se indicara explícitamente una alternativa, se podrían ignorar otros en caso de ambigüedad de sobrecarga. Puedo agregar una solicitud de función Jira para esto. – StaxMan

+0

Otra cosa: es interesante que haya un problema de sobrecarga aquí, ya que Jackson realmente permite una sobrecarga limitada. Específicamente, si el argumento fuera int o long (en lugar de double), el problema no ocurriría.Pero otros tipos primitivos (doble, flotante, booleano, char, byte, corto) no son compatibles de esta manera; aunque flotante y doble probablemente debería ser. Con la diferencia larga e interna se resuelve según lo que tiene JSON: los objetos JSON usan el setter POJO; Números JSON int o largos. – StaxMan

Respuesta

43

No es necesario cambiar el nombre del método setter para evitar ambigüedades. De lo contrario, estarás en el camino correcto con @JsonIgnore. Con @JsonIgnore en todos los métodos del mismo nombre que se ignorarán, el que se utiliza no necesita la anotación @JsonProperty.

Aquí hay un ejemplo simple para demostrar este punto.

input.json:{"value":"forty-two"}

Foo.java:

import java.io.File; 

import org.codehaus.jackson.annotate.JsonIgnore; 
import org.codehaus.jackson.map.ObjectMapper; 

public class Foo 
{ 
    String value; 

    public String getValue() {return value;} 
    public void setValue(String value) {this.value = value;} 

    @JsonIgnore 
    public void setValue(int value) {this.value = String.valueOf(value);} 

    public static void main(String[] args) throws Exception 
    { 
    ObjectMapper mapper = new ObjectMapper(); 
    Foo foo = mapper.readValue(new File("input.json"), Foo.class); 
    System.out.println(mapper.writeValueAsString(foo)); 
    } 
} 

Si no desea alterar los defs POJO vírgenes con una anotación de Jackson, a continuación, se puede utilizar una MixIn.

import java.io.File; 

import org.codehaus.jackson.annotate.JsonIgnore; 
import org.codehaus.jackson.map.ObjectMapper; 

public class Foo 
{ 
    String value; 

    public String getValue() {return value;} 
    public void setValue(String value) {this.value = value;} 
    public void setValue(int value) {this.value = String.valueOf(value);} 

    public static void main(String[] args) throws Exception 
    { 
    ObjectMapper mapper = new ObjectMapper(); 
    mapper.getDeserializationConfig().addMixInAnnotations(Foo.class, IgnoreFooSetValueIntMixIn.class); 
    Foo foo = mapper.readValue(new File("input.json"), Foo.class); 
    System.out.println(mapper.writeValueAsString(foo)); 
    } 
} 

abstract class IgnoreFooSetValueIntMixIn 
{ 
    @JsonIgnore public abstract void setValue(int value); 
} 
+0

Gracias, esto es exactamente lo que estaba buscando. – gregwhitaker

+0

¿Qué pasa cuando no puedes modificar la clase cuando es un tercero? ¿Hay un método para eso? – crunchdog

+1

Las instalaciones mixtas de Jackson pueden satisfacer sus necesidades. Le permite anotar efectivamente definiciones de tipos de terceros, sin alterar los originales. –

2

En los casos en que @JsonIgnore no ayuda (actualmente tengo un caso tal, pero todavía no estoy seguro de la razón), sino que también es posible utilizar @XmlTransient lugar.

3

En Jackson> 2,4 utilizado de manera directa:

mapper.addMixIn(Foo.class, IgnoreFooSetValueIntMixIn.class); 
Cuestiones relacionadas