2011-05-23 22 views
39

tengo una clase Java, Usuario:¿Cómo escribo un deserializador JSON personalizado para Gson?

public class User 
{ 
    int id; 
    String name; 
    Timestamp updateDate; 
} 

y recibo una lista JSON que contiene los objetos de usuario de un servicio web:

[{"id":1,"name":"Jonas","update_date":"1300962900226"}, 
{"id":5,"name":"Test","date_date":"1304782298024"}] 

He tratado de escribir una deserializer personalizado:

@Override 
public User deserialize(JsonElement json, Type type, 
         JsonDeserializationContext context) throws JsonParseException { 

     return new User(
      json.getAsJsonPrimitive().getAsInt(), 
      json.getAsString(), 
      json.getAsInt(), 
      (Timestamp)context.deserialize(json.getAsJsonPrimitive(), 
      Timestamp.class)); 
} 

Pero mi deserializador no funciona. ¿Cómo puedo escribir un deserializador JSON personalizado para Gson?

+0

ejemplo hace esto ayuda en absoluto? http://stackoverflow.com/questions/5845822/gson-deserializing-key-value-to-custom-object –

+0

¿Qué quiere decir que "no funciona"? ¿Cual es el problema? – ColinD

+1

¿Debería "date_date" ser "update_date"? –

Respuesta

45
@Override 
public User deserialize(JsonElement json, Type type, 
     JsonDeserializationContext context) throws JsonParseException { 

    JsonObject jobject = json.getAsJsonObject(); 

    return new User(
      jobject.get("id").getAsInt(), 
      jobject.get("name").getAsString(), 
      new Timestamp(jobject.get("update_date").getAsLong())); 
} 

Supongo que la clase de usuario tiene el constructor apropiado.

74

Me gustaría tener un enfoque ligeramente diferente de la siguiente manera, con el fin de minimizar el "manual" de análisis en mi código, ya que de otro modo un tanto innecesariamente haciendo en contra del propósito de por qué me gustaría usar una API como Gson en el primer lugar.

// output: 
// [User: id=1, name=Jonas, updateDate=2011-03-24 03:35:00.226] 
// [User: id=5, name=Test, updateDate=2011-05-07 08:31:38.024] 

// using java.sql.Timestamp 

public class Foo 
{ 
    static String jsonInput = 
    "[" + 
     "{\"id\":1,\"name\":\"Jonas\",\"update_date\":\"1300962900226\"}," + 
     "{\"id\":5,\"name\":\"Test\",\"update_date\":\"1304782298024\"}" + 
    "]"; 

    public static void main(String[] args) 
    { 
    GsonBuilder gsonBuilder = new GsonBuilder(); 
    gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES); 
    gsonBuilder.registerTypeAdapter(Timestamp.class, new TimestampDeserializer()); 
    Gson gson = gsonBuilder.create(); 
    User[] users = gson.fromJson(jsonInput, User[].class); 
    for (User user : users) 
    { 
     System.out.println(user); 
    } 
    } 
} 

class User 
{ 
    int id; 
    String name; 
    Timestamp updateDate; 

    @Override 
    public String toString() 
    { 
    return String.format(
     "[User: id=%1$d, name=%2$s, updateDate=%3$s]", 
     id, name, updateDate); 
    } 
} 

class TimestampDeserializer implements JsonDeserializer<Timestamp> 
{ 
    @Override 
    public Timestamp deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) 
     throws JsonParseException 
    { 
    long time = Long.parseLong(json.getAsString()); 
    return new Timestamp(time); 
    } 
} 

(esto supone que "date_date" debe ser "UPDATE_DATE", en la pregunta original.)

+2

Definitivamente prefiero este modelo: si Timestamp es lo único que falla en el análisis, es mejor hacer que Timestamp sea deserializable, en lugar de analizar manualmente todo el objeto User, cuando Gson ya sea perfectamente capaz de hacerlo. – dimo414

+0

pequeña edición. podemos usar "return new Timestamp (json.getAsLong());" en lugar de "long time = Long.parseLong (json.getAsString()); return new Timestamp (time);" – Nishanth

+0

También puede modelar el 'GsonBuilder', mejorando la legibilidad. –

Cuestiones relacionadas