2014-09-07 12 views
54

Gson'da birden fazla JSON alanını tek bir Java nesne üyesi değişkenine eşlemek için herhangi bir yol var mı? Her alan için birden çok GSON @SerializedName?

ı bir Java sınıfı var diyelim

...

public class MyClass { 
    String id; 
    String name; 
} 

İki farklı hizmetler ile bu tek bir sınıf kullanmak istiyorum. Ancak, bu iki hizmet sırasıyla ... ... onların veri döndürecek nasıl

{ "id": 5382, "user": "Mary" } 

{ "id": 2341, "person": "Bob" } 

... ve ... farklıdır.

JSON dizesindeki "person" ve "user" alanlarını hem Java nesnesindeki name alanına eşlemek için herhangi bir yol var mı?

(Not:. Ben sadece hiç bir Java nesnesine JSON dizesinden dönüştürmek gerekir - etrafında asla başka bir şekilde)

+0

basit ve mükemmel açıklama https://futurestud.io/tutorials/gson-model-annotations-multiple-deserialization-names-with-serializedname –

cevap

20

O GSON bir alana birden @SerializedName ek açıklamaları tanımlamak için desteklenmez.

Sebep: Varsayılan deserialization By bir LinkedHashMap ile yönetilmektedir ve anahtarlar gelen json saha adıyla (özel sınıfının alan adları veya serializedNames) tarafından tanımlanır ve bire bir eşleme vardır. Uygulamanın (nasıl desantizasyonunun nasıl çalıştığını) ReflectiveTypeAdapterFactory sınıfının Adapter<T>'un read(JsonReader in) yöntemine göre görebilirsiniz.

Çözüm:

class MyClassTypeAdapter extends TypeAdapter<MyClass> { 

    @Override 
    public MyClass read(final JsonReader in) throws IOException { 
     final MyClass myClassInstance = new MyClass(); 

     in.beginObject(); 
     while (in.hasNext()) { 
      String jsonTag = in.nextName(); 
      if ("id".equals(jsonTag)) { 
       myClassInstance.id = in.nextInt(); 
      } else if ("name".equals(jsonTag) 
        || "person".equals(jsonTag) 
        || "user".equals(jsonTag)) { 
       myClassInstance.name = in.nextString(); 
      } 
     } 
     in.endObject(); 

     return myClassInstance; 
    } 

    @Override 
    public void write(final JsonWriter out, final MyClass myClassInstance) 
      throws IOException { 
     out.beginObject(); 
     out.name("id").value(myClassInstance.id); 
     out.name("name").value(myClassInstance.name); 
     out.endObject(); 
    } 
} 

Test durumda:

Bir özel name, person ve user json etiketlerini kolları ve özel sınıfın MyClass adı alanına onları eşler TypeAdapter yazabilir
String jsonVal0 = "{\"id\": 5382, \"user\": \"Mary\" }"; 
    String jsonVal1 = "{\"id\": 2341, \"person\": \"Bob\"}"; 

    final GsonBuilder gsonBuilder = new GsonBuilder(); 
    gsonBuilder.registerTypeAdapter(MyClass.class, new MyClassTypeAdapter()); 
    final Gson gson = gsonBuilder.create(); 

    MyClass myClassInstance0 = gson.fromJson(jsonVal0, MyClass.class); 
    MyClass myClassInstance1 = gson.fromJson(jsonVal1, MyClass.class); 

    System.out.println("jsonVal0 :" + gson.toJson(myClassInstance0)); 
    // output: jsonVal0 :{"id":5382,"name":"Mary"} 

    System.out.println("jsonVal1 :" + gson.toJson(myClassInstance1)); 
    // output: jsonVal1 :{"id":2341,"name":"Bob"} 

Examples about TypeAdapters.

Edit 2016.04.06: As @Mathieu Castets onun cevabında yazmış, şimdi destekleniyor. (Yani bu soru için doğru cevaptır.)

kamu soyut String [] alternatif
İade: alan alternatif isimler bu serisi kaldırılan zaman
Varsayılan: {}

+0

İşte basit ve mükemmel bir açıklama https://futurestud.io/tutorials/gson-model-annotations-multiple-deserialization-names-with-serializedname –

130

Ekim 2015'te, Gson sürüm 2.4 (changelog), seri hale getirme sırasında @SerializedName için alternatif/çoklu adları kullanma yeteneğini ekledi. Daha fazla özel TypeAdapter gerek yok!

Kullanımı:

İşte
@SerializedName(value="name", alternate={"person", "user"}) 

https://google.github.io/gson/apidocs/com/google/gson/annotations/SerializedName.html

+0

Harika. Teşekkür ederim. – Mulgard

+1

Başka bir aptal çözümden ve bazı koşullardan beni kurtarır. Teşekkürler :) –

+0

İşte basit ve mükemmel bir açıklama https://futurestud.io/tutorials/gson-model-annotations-multiple-deserialization-names-with-serializedname –