2011-05-23 2 views
39

Ho una classe Java, l'utente:Come si scrive un deserializzatore JSON personalizzato per Gson?

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

e ricevo una lista JSON contenente oggetti utente da un webservice:

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

Ho cercato di scrivere un deserializzatore personalizzato:

@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)); 
} 

Ma il mio deserializzatore non funziona. Come posso scrivere un deserializzatore JSON personalizzato per Gson?

+0

Questo esempio aiuto a tutti? http://stackoverflow.com/questions/5845822/gson-deserializing-key-value-to-custom-object –

+0

Cosa intendi per "non funziona"? Qual è il problema? – ColinD

+1

"date_date" deve essere "update_date"? –

risposta

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())); 
} 

Suppongo che la classe utente abbia il costruttore appropriato.

74

Avrei adottato un approccio leggermente diverso come segue, in modo da ridurre al minimo l'analisi "manuale" nel mio codice, poiché altrimenti farebbe inutilmente qualcosa, in qualche modo, sconfiggere lo scopo del perché utilizzerei un'API come Gson, in primo luogo.

// 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); 
    } 
} 

(questo presuppone che "date_date" deve essere "UPDATE_DATE", nella domanda iniziale.)

+2

Preferisco decisamente questo modello - se Timestamp è l'unica cosa che non riesce a analizzare, meglio rendere Timestamp deserializable, piuttosto che analizzare manualmente l'intero oggetto User, quando Gson è già perfettamente in grado di farlo. – dimo414

+0

piccola modifica. possiamo usare "return new Timestamp (json.getAsLong());" invece di "long time = Long.parseLong (json.getAsString()); restituisce nuovo Timestamp (ora);" – Nishanth

+0

È inoltre possibile impostare un metodo di concatenazione di 'GsonBuilder', migliorando la leggibilità. –