2012-07-25 27 views
11

He publicado la pregunta erróneamente. Estoy publicando la pregunta correctamente aquí ...Jackson - Deserializar Clase genérica variable

Estoy recibiendo una cadena json como respuesta HTTP. Sé la estructura de eso. Es el siguiente:

public class Json<T> { 
    public Hits<T> hits; 
} 
public class Hits<T> { 
    public int found; 
    public int start; 
    public ArrayList<Hit<T>> hit; 
} 
public class Hit<T> { 
    public String id; 
    public Class<T> data; 
} 

El campo "datos" puede pertenecer a cualquier clase. Lo sabré en tiempo de ejecución solamente. Lo obtendré como un parámetro. Así es como estoy deserializando.

public <T> void deSerialize(Class<T> clazz) { 
    ObjectMapper mapper = new ObjectMapper(); 
    mapper.readValue(jsonString, new TypeReference<Json<T>>() {}); 
} 

Pero estoy recibiendo un error -

no pueden acceder a java.lang.class.Class privada() desde java.lang.Class. Error al establecer el acceso No se puede hacer accesible un constructor de java.lang.Class

+0

¿Por qué duplicar la pregunta (ver http://stackoverflow.com/questions/11664894/jackson-deserialize-using-generic-class/11681540)? – StaxMan

+0

ver http://stackoverflow.com/questions/17400850/is-jackson-really-unable-to-deserialize-json-into-a-generic-type – lisak

Respuesta

1

¿Está serializando y deserializando el objeto de Clase a JSON? Tal vez mantenerlo como String in Hit y crear getter adicional que lance Class.forName, p.

public class Hit { 
    public String id; 
    public String data; 
    public Class<?> getDataClass() throws Exception { 
     return Class.forName(data); 
    } 
} 
+0

He editado la pregunta completamente, ¿pueden responderla? – gnjago

+1

El error que recibió dice: "Quiero instalar un nuevo objeto Class pero no puedo ejecutar' new Class() 'porque el constructor es privado". Además, no tiene sentido. Por favor, pon una muestra de cadena JSON. Será mucho más fácil sugerir una solución en ese momento. Estoy bastante seguro de que serializar/deserializar la propiedad de tipo Clase es una ruta incorrecta. –

0

Deserialize clase genérica variables

...

¿Cómo le digo a Jackson? ¿Lo hará mejor Gson?

The Gson user guide includes a section sobre exactamente lo que entiendo que está tratando de lograr, a pesar de que el ejemplo documentado todavía puede ser incompleta.

In a blog post, I covered in more detail the solution using Gson 1.7.1. A continuación se muestra el ejemplo del código correspondiente.

Las soluciones similares (pero más complicadas) que usan Jackson (1.8.2) también se demuestran y se describen en la misma publicación del blog. (Los diferentes enfoques y ejemplos utilizan cientos de líneas de código, así que he de volver a colocar los omitió aquí.)

public class GsonInstanceCreatorForParameterizedTypeDemo 
{ 
public static void main(String[] args) 
{ 
    Id<String> id1 = new Id<String>(String.class, 42); 

    Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, 
    new IdInstanceCreator()).create(); 
    String json1 = gson.toJson(id1); 
    System.out.println(json1); 
    // actual output: {"classOfId":{},"value":42} 
    // This contradicts what the Gson docs say happens. 
    // With custom serialization, as described in a 
    // previous Gson user guide section, 
    // intended output may be 
    // {"value":42} 

    // input: {"value":42} 
    String json2 = "{\"value\":42}"; 

    Type idOfStringType=new TypeToken<Id<String>>(){}.getType(); 
    Id<String> id1Copy = gson.fromJson(json2, idOfStringType); 
    System.out.println(id1Copy); 
    // output: classOfId=class java.lang.String, value=42 

    Type idOfGsonType = new TypeToken<Id<Gson>>() {}.getType(); 
    Id<Gson> idOfGson = gson.fromJson(json2, idOfGsonType); 
    System.out.println(idOfGson); 
    // output: classOfId=class com.google.gson.Gson, value=42 
} 
} 

class Id<T> 
{ 
private final Class<T> classOfId; 
private final long value; 

public Id(Class<T> classOfId, long value) 
{ 
    this.classOfId = classOfId; 
    this.value = value; 
} 

@Override 
public String toString() 
{ 
    return "classOfId=" + classOfId + ", value=" + value; 
} 
} 

class IdInstanceCreator implements InstanceCreator<Id<?>> 
{ 
@SuppressWarnings({ "unchecked", "rawtypes" }) 
public Id<?> createInstance(Type type) 
{ 
    Type[] typeParameters = 
    ((ParameterizedType) type).getActualTypeArguments(); 
    Type idType = typeParameters[0]; 
    return new Id((Class<?>) idType, 0L); 
} 
} 
10

que se necesitan para construir JavaType explícitamente, si el tipo genérico es solamente disponible dinámicamente:

// do NOT create new ObjectMapper per each request! 
final ObjectMapper mapper = new ObjectMapper(); 

public Json<T> void deSerialize(Class<T> clazz, InputStream json) { 
    return mapper.readValue(json, 
     mapper.getTypeFactory().constructParametricType(Json.class, clazz)); 
} 
+0

Esto no funciona desde mi experiencia, aunque podría ser un error: https://github.com/FasterXML/jackson-databind/issues/254 – lisak

+0

El error de referencia tenía otro (s) problema (s) - resolución de tipo genérico como se muestra arriba funcionará, pero no aborda otros posibles problemas. – StaxMan

+0

Sí, mis disculpas, se resolvió aquí http://stackoverflow.com/questions/17400850/is-jackson-really-unable-to-deserialize-json-into-a-generic-type – lisak

2

ejemplo interfaz deserializar genérica:

public interface Deserializable<T> { 
    static final ObjectMapper mapper = new ObjectMapper(); 

    @SuppressWarnings("unchecked") 
    default T deserialize(String rawJson) throws IOException { 
     return mapper.readValue(rawJson, (Class<T>) this.getClass()); 
    } 
} 
0

cadena JSON que necesita ser deserializado deberá contener la información de tipo acerca PARAMET er T.
Deberá poner anotaciones Jackson en cada clase que se pueda pasar como parámetro T a la clase Json para que la información de tipo sobre el tipo de parámetro T pueda leerse/escribirse en cadena JSON por Jackson.

Supongamos que T puede ser cualquier clase que extienda la clase abstracta Result.

public class Json<T extends Result> { 
    public Hits<T> hits; 
} 

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT) 
@JsonSubTypes({ 
     @JsonSubTypes.Type(value = ImageResult.class, name = "ImageResult"), 
     @JsonSubTypes.Type(value = NewsResult.class, name = "NewsResult")}) 
public abstract class Result { 

} 

public class ImageResult extends Result { 

} 

public class NewsResult extends Result { 

} 

Una vez cada uno de la clase (o su supertipo común) que se puede pasar como parámetro T está anotado, Jackson incluirá información acerca de parámetro T en el JSON.Tal JSON puede deserializarse sin conocer el parámetro T en tiempo de compilación.
Este Jackson documentation link habla de deserialización polimórfica pero también es útil para referirse a esta pregunta.

Cuestiones relacionadas