2011-02-14 21 views
7

Me gustaría leer en la cadena {"a": 1.0} como un objeto genérico de Java, manteniendo el mismo formato de cadena. Sin embargo, cuando intento, Jackson cambia automáticamente la representación interna a {a = 1}. En otras palabras, ¿cómo puedo obtener el siguiente código para imprimir {"a": 1.0} en lugar de {a = 1}? Tenga en cuenta que tengo que leerlo como Object (debido a otras limitaciones del programa).serialización genérica de objetos en Jackson con Java

import org.codehaus.jackson.map.ObjectMapper; 

public class Main { 

    public static void main(String[] args) { 
     try 
    { 
      ObjectMapper mapper = new ObjectMapper(); 
      Object myObject = mapper.readValue("{\"a\": 1.0}", Object.class); 
      System.out.println(myObject.toString());    
    } 
    catch (Exception e) 
    { 
     e.printStackTrace(); 
     System.err.println(e.getMessage()); 
    } 
    } 

} 
+2

Esto no tiene sentido para mí. El objeto no tiene ninguna propiedad para la tecla "a", entonces, ¿cómo puede leerse así? ¿No necesitas crear una clase con esta propiedad? –

+1

Tal vez está asumiendo que Jackson de alguna manera calcula telepáticamente el tipo esperado ... lo que realmente ocurre es que Object.class tiene un manejo especial con Jackson: creará mapeos "naturales" a Maps, Lists y tipos de wrappers (que obviamente son todos Objetos)) – StaxMan

Respuesta

3

Necesita una clase existente que coincida con la estructura json deseada. El objeto no es esa clase. Todavía se puede hacer referencia a ella como Object, si lo que se necesita:

Object myObject = mapper.readValue("{\"a\": 1.0}", SomeClass.class); 
2

Si utiliza un depurador, se verá que el tipo del objeto devuelto es LinkedHashMap. Entonces, lo que ves es el resultado de LinkedHashMap.toString(). No hay manera de Jackson para cambiar eso, por lo que puede convertirlo a un mapa y la creación de la cadena de sí mismo o pedir otro tipo de retorno que genera el JSON de cuerdas para usted:

if(myObject instanceof Map<?, ?>){ 
    final Map<?, ?> map = (Map<?, ?>) myObject; 
    final StringBuilder sb = new StringBuilder("{"); 
    boolean first = true; 
    for(final Entry<?, ?> entry : map.entrySet()){ 
     if(first){ 
      first = false; 
     } else{ 
      sb.append(","); 
     } 
     sb.append("\n\t'") 
      .append(entry.getKey()) 
      .append("':'") 
      .append(entry.getValue()) 
      .append("'"); 
    } 
    if(!first){ 
     sb.append("\n"); 
    } 
    sb.append("}"); 
    System.out.println(sb.toString()); 

} else{ 
    System.out.println(myObject); 
} 

Salida:

{ 
    'a':'1.0' 
} 
+3

Jackson tiene soporte para escribir mapas para que pueda hacer algo como: 'System.out.println (mapper.writeValueAsString (myObject)) 'en lugar de escribir su propio serializador. – oconnor0

2

Cuando se le dice a Jackson que vincule JSON en Object.class, hace exactamente eso; pero como no tiene conocimiento a priori de lo que podría haber en ese JSON (o qué clases podría querer usar), tiene que usar la mayoría de los tipos básicos de Java: Mapas, Listas, Números, Booleanos y Cadenas. Entonces cualquier objeto JSON está representado por Map; JSON Array por lista, y así sucesivamente.

Si desea un objeto personalizado, debe especificar su tipo; o, al serializar, habilitar la inclusión de información de tipo explícita ("manejo de tipo polimórfico"). Esto agregará el nombre de clase o el nombre de tipo y se puede usar para deserializar de nuevo al tipo exacto.

Para hacer esto, cualquiera de los tipos (o uno de sus supertipos) debe usar la anotación @JsonTypeInfo; o, si es una propiedad Object, @JsonTypeInfo para la propiedad (campo o método).

7

El objeto creado será un mapa (como los otros comentarios) y así toString produce lo que está viendo, {a = 1}. Para obtener su código para imprimir algo más cercano a su valor de entrada, es necesario utilizar Jackson a escribir de nuevo con algo como:

System.out.println(mapper.writeValueAsString(myObject)); 

Eso me da lo que creo que está buscando:

{"a":1.0} 

En otras palabras, Jackson ha deserializado su cadena de entrada en un objeto de Java arbitrario. Cuando llama al toString en el objeto, por supuesto, se usa su propio toString. Esto puede escribir el objeto como le plazca, incluido el uso del método Object. Para reproducir la cadena de entrada, debe usar Jackson para serializar nuestro objeto de nuevo.

Cuestiones relacionadas