2012-05-29 15 views
10

He la clase siguiente:Fuerza Jackson para añadir envoltura addional utilizando anotaciones

public class Message { 
    private String text; 

    public String getText() { 
     return text; 
    } 

    public void setText(String text) { 
     this.text = text; 
    }  
} 

Al convertir la instancia a JSON usando Jackson por defecto me sale:

{"text":"Text"} 

me gustaría obtener:

{"message":{"text":"Text"}} 

¿hay alguna anotación JAXB/Jackson que puedo utilizar para lograr mi objetivo?

Como solución, puedo envolver mi clase con otra clase:

public class MessageWrapper { 
    private Message message; 

    public Message getMessage() { 
     return message; 
    } 

    public void setMessage(Message message) { 
     this.message = message; 
    } 
} 

o una solución más genérica:

public class JsonObjectWrapper<T> { 
    /** 
    * Using a real map to allow wrapping multiple objects 
    */ 
    private Map<String, T> wrappedObjects = new HashMap<String, T>(); 

    public JsonObjectWrapper() { 
    } 

    public JsonObjectWrapper(String name, T wrappedObject) { 
     this.wrappedObjects.put(name, wrappedObject); 
    } 

    @JsonAnyGetter 
    public Map<String, T> any() { 
     return wrappedObjects; 
    } 

    @JsonAnySetter 
    public void set(String name, T value) { 
     wrappedObjects.put(name, value); 
    } 
} 

que se pueden utilizar de este modo:

Message message = new Message(); 
message.setText("Text"); 
JsonObjectWrapper<Message> wrapper = new JsonObjectWrapper<Message>("message", message); 

¿Hay alguna anotación JAXB/Jackson que pueda usar para lograr ¿mi meta?

Gracias.

Respuesta

12

En la solución: no es necesario en absoluto esos getters/setters, por lo que sólo podría tener:

public class MessageWrapper { 
    public Message message; 
} 

o quizás añadir comodidad constructor:

public class MessageWrapper { 
    public Message message; 
    @JsonCreator 
    public MessageWrapper(@JsonProperty("message") Message m) { 
     message = m; 
    } 
} 

Hay una manera de añadir envoltura también; con 1.9 puede usar SerializationConfig.Feature.WRAP_ROOT_ELEMENT y DeserializationConfig.Feature.UNWRAP_ROOT_ELEMENT. Y si desea cambiar el nombre del derivador (por defecto es simplemente el nombre de clase no calificado), puede utilizar @JsonRootName anotación

Jackson 2.0 añade opciones más dinámicas a través de ObjectReader y ObjectWriter, así como las anotaciones JAX-RS.

+0

StaxMan, si el nombre del elemento raíz de la cadena JSON tiene que ser ignorado durante la serialización, hace Jackson 1.9 nos obligan a establecer la función 'DeserializationConfig.Feature.UNWRAP_ROOT_ELEMENT' solo o la adición de la anotación' @JsonRootName 'se requiere también? – asgs

+1

Tendría que verificar: UNWRAP podría ser suficiente; La pregunta es si el nombre tiene que mapear. Pero incluso sin '@ JsonRootName', existe el nombre predeterminado (nombre de clase simple), que puede funcionar bien. – StaxMan

+0

funcionó! muchas gracias. – asgs

4

Fue triste saber que debe escribir una serialización personalizada con el objetivo simple de envolver una clase con un objeto etiquetado. Después de jugar con la escritura de un serializador personalizado, llegué a la conclusión de que la solución más simple es un contenedor genérico. Aquí es tal vez una aplicación más simple de su ejemplo anterior:

public final class JsonObjectWrapper { 
    private JsonObjectWrapper() {} 

    public static <E> Map<String, E> withLabel(String label, E wrappedObject) { 
     HashMap<String, E> map = new HashMap<String, E>(); 
     map.put(label, wrappedObject); 
     return map; 
    } 
} 
0

una mejor manera sencilla/hacerlo:

@JsonRootName(value = "message") 
public class Message { ...} 

a continuación, utilizar
new ObjectMapper().configure(SerializationFeature.WRAP_ROOT_VALUE, true).writeValueAs...

2

Siempre y cuando no te importa el json tiene un capital m en message, entonces la forma más sencilla de hacer esto es anotar su clase con @JsonTypeInfo.

necesita añadir:

@JsonTypeInfo(include=As.WRAPPER_OBJECT, use=Id.NAME)` 
public class Message { 
    // ... 
} 

para obtener {"Message":{"text":"Text"}}

0

Si se utiliza la primavera, a continuación, en Agregar archivo application.properties siguiente: -

spring.jackson.serialization.WRAP_ROOT_VALUE = true

Y luego use la anotación @JsonRootName en cualquiera de sus clases que desee serializar. p.ej.

@JsonRootName("user") 
public class User { 
    private String name; 
    private Integer age; 
} 
Cuestiones relacionadas