2017-04-06 38 views
0

如何设置超一流的“查找”的id属性,名称解析JSON时解析国家的JSON阵列 时设置超类属性:如何使用GSON

[ {"ID":5, "CountryNameEN":"UK" }, {"ID":6, "CountryNameEN":"USA" } ] 

例如,当我调用get_lookups_countries()API与改造2 &解析响应与谷歌Gson库,我想设置超类实例成员ID为&名称与派生类相同的值“国家”

@GET(Constants.LookUps.GET_COUNTRIES) Call<List<Country>> get_lookups_countries(); 
Gson gson = new GsonBuilder() 
      .setLenient() 
      .registerTypeAdapter(LookUp.class,new LookupsDeserializer()) 
      .create(); 

    HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); 
    logging.setLevel(HttpLoggingInterceptor.Level.BODY); 
    OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder(); 

    Retrofit retrofit = new Retrofit.Builder() 
      .baseUrl(BASE_URL) 
      .client(okHttpClient.build()) 
      .addConverterFactory(GsonConverterFactory.create(gson)) 
      .build(); 
    return retrofit.create(APIEndpointVatTax.class); 
public class LookUp { 
    int id; 
    String name; 
} 


public class Country extends LookUp { 

     @SerializedName("ID") 
     @Expose 
     private Integer iD; 

     @SerializedName("CountryNameEN") 
     @Expose 
     private String countryNameEN; 
} 
+0

Lookup ID和Country iD是不同的吗? –

+0

不,相同的值 –

+1

那你为什么需要超类? –

回答

1

你似乎有一些问题,你的JSON映射:你想绑定的超类字段子类字段,然而这是哪里的接口可能是你更好的选择,因为你的意图只是询问反序列化的对象的id和名称。

我会做这样的:

interface LookUp { 

    int getId(); 

    String getName(); 

} 
final class CountryByInterface 
     implements LookUp { 

    @SerializedName("ID") 
    private final Integer id = null; 

    @SerializedName("CountryNameEN") 
    private final String name = null; 

    @Override 
    public int getId() { 
     return id; 
    } 

    @Override 
    public String getName() { 
     return name; 
    } 

} 

所以它可以很容易使用(Java的8只为演示目的):

final Gson gson = new Gson(); 
final Type countryListType = new TypeToken<List<CountryByInterface>>() { 
}.getType(); 
try (final Reader reader = getPackageResourceReader(Q43247712.class, "countries.json")) { 
    gson.<List<CountryByInterface>>fromJson(reader, countryListType) 
      .stream() 
      .map(c -> c.getId() + "=>" + c.getName()) 
      .forEach(System.out::println); 
} 

如果出于某种正当理由你确实需要超级类来持有这样的领域,你必须实现后处理器(灵感来自PostConstructAdapterFactory)。再说了,

abstract class AbstractLookUp { 

    int id; 
    String name; 

    abstract int getId(); 

    abstract String getName(); 

    final void postSetUp() { 
     id = getId(); 
     name = getName(); 
    } 

} 
final class CountryByClass 
     extends AbstractLookUp { 

    @SerializedName("ID") 
    private final Integer id = null; 

    @SerializedName("CountryNameEN") 
    private final String name = null; 

    @Override 
    int getId() { 
     return id; 
    } 

    @Override 
    String getName() { 
     return name; 
    } 

} 
final Gson gson = new GsonBuilder() 
     .registerTypeAdapterFactory(new TypeAdapterFactory() { 
      @Override 
      public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) { 
       // Check if it's a class we can handle: AbstractLookUp 
       if (AbstractLookUp.class.isAssignableFrom(typeToken.getRawType())) { 
        // Get the downstream parser for the given type 
        final TypeAdapter<T> delegateTypeAdapter = gson.getDelegateAdapter(this, typeToken); 
        return new TypeAdapter<T>() { 
         @Override 
         public void write(final JsonWriter out, final T value) 
           throws IOException { 
          delegateTypeAdapter.write(out, value); 
         } 

         @Override 
         public T read(final JsonReader in) 
           throws IOException { 
          // Deserialize it as an AbstractLookUp instance 
          final AbstractLookUp abstractLookUp = (AbstractLookUp) delegateTypeAdapter.read(in); 
          // And set it up 
          abstractLookUp.postSetUp(); 
          @SuppressWarnings("unchecked") 
          final T result = (T) abstractLookUp; 
          return result; 
         } 
        }; 
       } 
       return null; 
      } 
     }) 
     .create(); 
final Type countryListType = new TypeToken<List<CountryByClass>>() { 
}.getType(); 
try (final Reader reader = getPackageResourceReader(Q43247712.class, "countries.json")) { 
    gson.<List<CountryByClass>>fromJson(reader, countryListType) 
      .stream() 
      .map(c -> ((AbstractLookUp) c).id + "=>" + ((AbstractLookUp) c).name) 
      .forEach(System.out::println); 
} 

两个例子都产生

5 = >英国
6 = >美国

但是我觉得第一种方法更好地设计和多更容易使用,哪里第二个演示如何配置Gson来实现复杂的(de)序列化策略。

+0

最佳解决方案!谢谢Lyubomyr,你节省了我的时间。 感谢您的支持和帮助。 –

+0

@FarisAbuSaleem没问题,不客气。 –