2011-04-18 10 views
8

¿Cuál es la mejor y más fácil forma de crear beans de forma personalizada (no llamando al constructor predeterminado) mientras se deserializa de JSON utilizando la biblioteca de Jackson? Descubrí que hay una interfaz JsonDeserializer que podría implementar, pero no estoy muy seguro de cómo conectarla en el ObjectMapper.¿Cómo crear instancias de beans de forma personalizada con Jackson?

ACTUALIZACIÓN # 1: Creo que se requieren más detalles para mi pregunta. Por defecto, el deserializador de Jackson usa un constructor predeterminado para crear beans. Me gustaría poder implementar la creación de instancias del bean llamando a una fábrica externa. Entonces, lo que necesito es solo una clase del bean que necesita ser instanciada. La fábrica devolverá la instancia que luego se le puede proporcionar a Jackson para la población de la propiedad y así sucesivamente.

Tenga en cuenta que no me preocupa la creación de valores simples/escalares, como cadenas o números, solo los beans están en el área de mi interés.

Respuesta

0

se pone el deserializer en el objeto Java que desea hacer el mapeado en JSON:

@JsonDeserialize(using = PropertyValueDeserializer.class) 
public class PROPERTY_VALUE implements Serializable{ 

y luego en el deserializador se puede, por ejemplo, hacer:

@Override 
public PROPERTY_VALUE deserialize(JsonParser jsonParser, 
        DeserializationContext deserializationContext) 
      throws IOException, JsonProcessingException { 

    String tmp = jsonParser.getText(); // { 
    jsonParser.nextToken(); 
    String key = jsonParser.getText(); 
    jsonParser.nextToken(); 
    String value = jsonParser.getText(); 
    jsonParser.nextToken(); 
    tmp = jsonParser.getText(); // } 

    PROPERTY_VALUE pv = new PROPERTY_VALUE(key,value); 
    return pv; 
} 

Si no desea utilizar las anotaciones, que necesita para aprobar el asignador una DeserializerProvider que puede proporcionar el deserializer adecuado para un tipo dado.

mapper.setDeserializerProvider(myDeserializerProvider); 

Para los constructores - por supuesto que puede generar la clase de destino llamando a una fábrica dentro de la deserializer:

String value = jsonParser.getText(); 
    jsonParser.nextToken(); 
    tmp = jsonParser.getText(); // } 

    MyObject pv = MyObjectFactory.get(key); 
    pv.setValue(value); 
    return pv; 
} 

Pero entonces pude haber malinterpretado su actualización

+0

Gracias Heiko. Jackson usa por defecto el constructor predeterminado de un bean para crear la instancia. Lo que me gustaría hacer es crear realmente el frijol usando una fábrica externa. Actualizaré mi pregunta con algunos detalles en un segundo. –

+0

¿Cómo podría hacer esto sin usar anotaciones? –

+1

Al usar anotaciones mix-in, que no necesitan agregarse directamente a la clase en sí, sino a otras clases de "mezcla". Esto hace posible utilizar el enfoque de anotación con libs de terceros. – StaxMan

8

algunas cosas que pueden ayuda ...

En primer lugar, puede usar @JsonCreator para definir el constructor alternativo a usar (todos los argumentos deben estar anotados con @JsonProperty porque bytecode tiene sin nombres), o una fábrica estática. Todavía sería parte de la clase de valor, pero puede ayudar a admitir objetos inmutables.

En segundo lugar, si desea un proceso de deserialización verdaderamente personalizado, puede consultar http://wiki.fasterxml.com/JacksonHowToCustomDeserializers que explica cómo registrar deserializadores personalizados.

Una cosa que Jackson actualmente echa de menos es el soporte para objetos de estilo constructor; hay una solicitud de función para agregar soporte (y el plan es agregar soporte en el futuro una vez que los desarrolladores tengan tiempo).

Cuestiones relacionadas