2013-03-20 7 views
7

Ich versuche, einen benutzerdefinierten Gson Serializer/Deserialiser für eine Liste von BasicNameValuePair-Objekten zu implementieren.Benutzerdefinierter Serializer - Deserializer mit GSON für eine Liste von BasicNameValuePairs

sah ich die Teillösung Code (für die Serialisierung) hier: How do I get Gson to serialize a list of basic name value pairs?

jedoch auch Deserialisierung implementieren ich wollte, und ich versuchte, meine Chancen und der Code ist hier:

package dto; 

import java.io.IOException; 
import java.util.ArrayList; 
import java.util.List; 

import org.apache.http.message.BasicNameValuePair; 


import com.google.gson.TypeAdapter; 
import com.google.gson.stream.JsonReader; 
import com.google.gson.stream.JsonWriter; 


    public class KeyValuePairSerializer extends TypeAdapter<List<BasicNameValuePair>> { 
     @Override 
     public void write(JsonWriter out, List<BasicNameValuePair> data) throws IOException { 
      out.beginObject(); 
      for(int i=0; i<data.size();i++){ 
       out.name(data.get(i).getName()); 
       out.value(data.get(i).getValue()); 
      } 
      out.endObject(); 
     } 

     @Override 
     public List<BasicNameValuePair> read(JsonReader in) throws IOException { 
      ArrayList<BasicNameValuePair> list=new ArrayList<BasicNameValuePair>(); 
      in.beginObject(); 
      while (in.hasNext()) { 
       String key = in.nextName(); 
       String value = in.nextString(); 
       list.add(new BasicNameValuePair(key,value)); 
      } 
      in.endObject(); 
      return list; 
     } 

} 

-Code initialisieren und füllen Sie die Liste

ArrayList<BasicNameValuePair> postParameters=new ArrayList<BasicNameValuePair>(); 
postParameters.add(new BasicNameValuePair("some_key","some_value")); 

Und hier ist der Code die neue KeyValuePairSerializer Klasse zu verwenden:

 GsonBuilder gsonBuilder= new GsonBuilder(); 
     gsonBuilder.registerTypeAdapter(KeyValuePairSerializer.class, new KeyValuePairSerializer()); 
     Gson gson1=gsonBuilder.create(); 

     //serialization works just fine in the next line 
     String jsonUpdate=gson1.toJson(postParameters, KeyValuePairSerializer.class); 


     ArrayList<BasicNameValuePair> postParameters2 = new ArrayList<BasicNameValuePair>(); 
     //postParameters2 = gson1.fromJson(jsonUpdate, KeyValuePairSerializer.class); //? how to cast properly 
     //deserialization throws an error, it can't cast from ArrayList<BasicNameValuePair> to KeyValuePairSerializer 
     gson1.fromJson(jsonUpdate, KeyValuePairSerializer.class); 

Das Problem ist, dass es eine Ausnahme am Ende wirft und ich weiß nicht, wo genau das Problem ist, und immer noch nicht sicher, wie die letzte Zeile zu schreiben, zu erhalten das Ergebnis zurück in der neuen postParameters2 ArrayList.

Antwort

8

vom GSON Collections Examples Angepasst:

GsonBuilder gsonBuilder= new GsonBuilder(); 
gsonBuilder.registerTypeAdapter(KeyValuePairSerializer.class, new KeyValuePairSerializer()); 
Gson gson1=gsonBuilder.create(); 

Type collectionType = new TypeToken<ArrayList<BasicNameValuePair>>(){}.getType(); 
ArrayList<BasicNameValuePair> postParameters2 = gson1.fromJson(jsonUpdate, collectionType); 
+0

Doing so etwas wird meine neue definierte Klasse KeyValuePairSerializer ignorieren und nicht die überschriebene Methode aufrufen: lesen. – Arise

+0

Eigentlich ignoriert es es nicht, wenn Sie 'registerTypeAdapter()' aufrufen, wie Sie in der Frage getan haben. – Nachi

+0

Es scheint nicht der Fall zu sein. RegisterTypeAdapter scheint nur für den Serializer nicht für Deserializer zu funktionieren. – Arise

1

registerTypeAdapter scheint nur für die Serializer arbeiten nicht für Deserializer.

Der einzige Weg, die außer Kraft gesetzt lesen Funktion des KeyValuePairSerializer zu nennen ist, die nennen: gson1.fromJson(jsonUpdate, KeyValuePairSerializer.class); ohne Speichern des Ergebniswert in einer Variablen. Während es die Funktion gut verarbeitet, wird es einen Fehler in der Klasse gson werfen, da es nicht in der Lage ist, von der ArrayList auf den KeyValuePairSerializer zu konvertieren. Und ich verstehe irgendwie warum (Löschen denke ich), weiß einfach nicht, wie man es richtig macht.

Wie auch immer, ich habe einen Workaround gefunden, um dieses Problem zu lösen. Es scheint, dass stattdessen das Gson Objekt der Registrierung und registerTypeAdapter aufrufen und dann gson1.toJson(Object src, Type typeOfSrc) und gson1.fromJson(String json,Class <T> classOfT) ich mit für die Deserialisierung mit etwas wegkommen kann einfacher wie:

KeyValuePairSerializer k= new KeyValuePairSerializer(); 
parametersList = (ArrayList<BasicNameValuePair>)k.fromJson(jsonUpdate); 
-1

ich diesen Blog für GSON Collection Examples gefolgt. Link ist einfach zu verstehen und zu implementieren.

public class TimeSerializer implements JsonSerializer<time> { 

    /** 
    * Implementing the interface JsonSerializer. 
    * Notice that the the interface has a generic 
    * type associated with it. 
    * Because of this we do not have ugly casts in our code. 
    * {@inheritDoc} 
    */ 
    public JsonElement serialize(
        final Time time, 
        final Type type, 
        final JsonSerializationContext jsonSerializationContext) { 

     /** 
     * Returning the reference of JsonPremitive 
     * which is nothing but a JSONString. 
     * with value in the format "HH:MM" 
     */ 
     return new JsonPrimitive(String.format("%1$02d:%2$02d", 
           time.getHour(), time.getMinute())); 
    } 
0

Beide JsonObject des und benehmen sich die Namevaluepair in ähnlicher Weise wie Wörterbücher, glaube ich nicht, dass Sie einen in die andere umwandeln müssen, wenn der Anwendungsfall ähnlich ist. Außerdem können Sie mit JsonObject Ihre Werte noch einfacher behandeln (anstatt das Array der Wertepaare durchzublättern, um den Schlüssel zu finden, den Sie für den Wert benötigen, verhält sich JsonObject ähnlich wie Map, so dass Sie den Namen des Schlüssels direkt aufrufen können und es wird die gewünschte Eigenschaft zurück):

jsonObject.get("your key").getAsString(); (getAsBoolean(), getAsInt(), etc). 

Für Ihren Fall würde ich einen JsonObject aus der Zeichenfolge, Antwort oder einen Stream erstellen und dann zugreifen, als eine Karte (wie oben dargestellt):

JsonParser parser = new JsonParser(); 
JsonObject o = (JsonObject)parser.parse("your json string");