2012-07-19 15 views
6

Me enfrentan los siguientes problemas. Cuando se pasa Jackson serializador una envuelta primitiva para la serialización, esta primitiva se serializa como es, por ejemplo:Serialización de objetos primitivos raíz con Jackson

objectMapper = new ObjectMapper(); 

StringWriter w = new StringWriter(); 
objectMapper.writeValue(w, Integer.valueOf(10)); 
System.out.println(w.toString()); 

produce 10 como salida. Sin embargo, 10 no es un JSON válido (según jsonlint) y debe estar entre corchetes ([10], por lo que será una matriz de elemento único) o entre llaves ({value:10}, por lo que será un objeto con propiedad ficticia) . El problema afecta a los números, java.lang.String, java.util.Date, ...

Mi pregunta es: ¿Cómo hacer que Jackson realice la envoltura? ¿Jackson no debería producir siempre un JSON válido?

He analizado el comportamiento de Jackson con SerializationConfig.Feature.WRAP_ROOT_VALUE activado: no funciona como esperaba. Las primitivas ahora se serializan a JSON válido ({"Integer":10}), pero los beans Java "normales" también se envuelven, lo que no se desea ({"MyBean":{"field":value, ...}} en lugar de {"field":value, ...}).

Si alguien puede aconsejar cómo personalizar Jackson, quizás con un serializador personalizado. La dificultad sería que es necesario distinguir la envoltura de la raíz primitiva (que debe envolverse) de la propiedad de la primitiva del frijol (no necesita envolverse).

Para completar la historia: Jackson serializer se utiliza como conversor de mensajes para Spring MVC, y dudo que sea bastante fácil escribir un gancho para interceptar la serialización de primitivos (que no llamará a Jackson pero simplemente devolverá "[" + String.toString(obj) + "]" cuando sea necesario) Así que preferiría la solución con el afinado Jackson.

+0

Recomiendo iniciar una solicitud de mejora en https://github.com/FasterXML/jackson-databind/issues –

Respuesta

3

Por último, el serializador personalizado

import java.io.IOException; 

import org.codehaus.jackson.JsonGenerationException; 
import org.codehaus.jackson.JsonGenerator; 
import org.codehaus.jackson.map.SerializerProvider; 
import org.codehaus.jackson.map.ser.std.ScalarSerializerBase; 

public class NumberSerializer extends ScalarSerializerBase<Number> { 

    protected NumberSerializer() { 
     super(Number.class); 
    } 

    @Override 
    public void serialize(Number value, JsonGenerator jgen, SerializerProvider provider) throws IOException, 
       JsonGenerationException { 
     if (jgen.getOutputContext().inRoot()) { 
      jgen.writeStartArray(); 
      jgen.writeNumber(value.longValue()); 
      jgen.writeEndArray(); 
     } 
     else { 
      jgen.writeNumber(value.longValue()); 
     } 
    } 
} 

hizo un trabajo para mí. El serializador se puede registrar como módulo (ver here).

Nota cuando se utiliza este serializador: Como convierte todas las primitivas en matrices primitivas con un solo elemento, se rompe el principio de reflexión en un sentido que A != desrialize(serialize(A)) donde A es primitivo.

Cuestiones relacionadas