2013-03-20 7 views
7

Próbuję zaimplementować niestandardowy serializator gson/deserialiser dla niektórych obiektów BasicNameValuePair.Niestandardowy serializer - deserializator używający GSON do listy BasicNameValuePairs

Widziałem częściowy kod Solution (dla serializacji) tutaj: How do I get Gson to serialize a list of basic name value pairs?

Jednak chciałem realizować również deserializacjia i próbowałem moje szanse i kod jest tutaj:

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 w celu zainicjowania i wypełnienia listy

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

Tutaj jest kod do korzystania z nowej klasy KeyValuePairSerializer:

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

Problemem jest to, że zgłasza wyjątek na końcu i nie wiem, gdzie dokładnie jest problem i nadal nie wiem, jak napisać ostatnią linię, aby uzyskać wynik w nowej specyfikacji PostParameters2 ArrayList.

Odpowiedz

8

Adaptacja GSON Collections Examples:

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

Wykonywanie takich czynności zignoruje moją nową zdefiniowaną klasę KeyValuePairSerializer i nie wywoła metody overriden: read. – Arise

+0

Właściwie to go nie zignoruje, jeśli wywołasz 'registerTypeAdapter()' tak, jak zrobiłeś to w pytaniu. – Nachi

+0

Nie wydaje się, żeby tak było. registerTypeAdapter wydaje się działać tylko dla serializera, a nie dla deserializera. – Arise

1

registerTypeAdapter wydaje się działać tylko dla serializatora nie dla Deserializatora.

Jedynym sposobem, aby wywołać nadpisane czytać funkcję KeyValuePairSerializer jest wywołanie: gson1.fromJson(jsonUpdate, KeyValuePairSerializer.class); bez zapisywania wartości wynik w zmiennej. Podczas gdy funkcja będzie przetwarzać poprawnie, spowoduje to błąd w klasie Gson, ponieważ nie będzie mógł rzutować z ArrayList na KeyValuePairSerializer. I rozumiem, dlaczego (zgaduję, chyba), po prostu nie wiem, jak to zrobić właściwie.

W każdym razie znalazłem sposób rozwiązania tego problemu. Wydaje się, że zamiast rejestracji obiektu gson i nazywając registerTypeAdapter a następnie za pomocą gson1.toJson(Object src, Type typeOfSrc) i gson1.fromJson(String json,Class <T> classOfT) mogę uciec na deserializacji z czegoś prostszego jak:

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

Śledziłem ten blog dla GSON Collection Examples. Link jest prosty do zrozumienia i wdrożenia.

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

Zarówno JSONObject i zachowywać NameValuePair w sposób podobny do słowników, nie sądzę, trzeba konwertować jeden w drugi, jeśli przypadek użycia jest podobny. Dodatkowo JsonObject pozwala ci leczyć twoje wartości jeszcze łatwiej (zamiast przechodzenia przez tablicę par wartości, aby znaleźć klucz, którego potrzebujesz, aby uzyskać jego wartość, JsonObject zachowuje się podobnie do mapy w taki sposób, że możesz bezpośrednio wywołać nazwę klucza i będzie to powrót pożądaną właściwość):

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

Twoim przypadku bym stworzyć JSONObject od strun, odpowiedzi lub strumienia, a następnie uzyskać dostęp go jako mapę (jak pokazano powyżej):

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