Gson 解析之 - 如何讓 json 鍵和實體類的屬性名不一樣

Gson 解析之 - 如何讓 json 鍵和實體類的屬性名不一樣

最近Gson用的比較多,用的時候一直有一個疑問,難道本地的實體類的屬性名一定要和Json的鍵一一對應(yīng)嗎?

json數(shù)據(jù)

{
  "name": "wangzhen",
  "age": 20,
  "tall": "176",
  "sex": "male"
}

對應(yīng)的實體類

public class Person1 {
    String name;
    String age;
    String sex;
    String tall;
}

一切看起來都是那么的美好,但是如果有一天,我們從另一個接口上,請求下來的數(shù)據(jù)是這樣的呢?

{
  "person_name": "wangzhen",
  "person_age": 20,
  "tall": "176",
  "person_sex": "male"
}

那我們的實體類豈不是要寫成這樣?

public class Person2 {
    String first_name;
    String person_name;
    String person_age;
    String person_sex;
}

可以試一下Person1

    Gson gson = new Gson();
    InputStream inputStream = null;
    inputStream = new FileInputStream(new File("json file path"));
    InStream2String converter = new InStream2String();
    String json = converter.convert(inputStream);
    Person person = gson.fromJson(json, Person1.class);
    System.out.println(person);

=== output ===
Person1{name='null', age='null', sex='null', tall='176'}

簡直不能忍
可是有什么辦法嗎?想到的一個解決方案就是為每一個實體類的屬性添加一個注解,在注解中標明該屬性對應(yīng)json的值,比如上面的 json 的 person_name 應(yīng)該對應(yīng) Person 的 name 屬性。
有思路就簡單咯,自己動手豐衣足食

新建一個注解,就叫Map吧

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Map {
    String value();
}

現(xiàn)在的屬性應(yīng)該是這個樣子的,有點感覺了。

@Map("person_name") String name;
@Map("person_age") String age;
@Map("person_sex") String sex;

在運行時,只需要動態(tài)獲取注解里面的值,就可以得到當前屬性應(yīng)當對應(yīng)的json的鍵,所以就可以起到屬性名與json鍵不同的效果了
好了,只需要去 818 Gson的源碼,然后用一個裝飾模式為Gson動態(tài)的添加一個職責差不多咯

但是! too young, too naive!

跟蹤源碼的時候發(fā)現(xiàn),會調(diào)用
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory
這個類中的 這個方法

  private String getFieldName(Field f) {
    SerializedName serializedName = f.getAnnotation(SerializedName.class);
    return serializedName == null ? fieldNamingPolicy.translateName(f) : serializedName.value();
  }

尼瑪,這 SerializedName又是什么鬼。。
點進去看一下

SerializedName注解的源碼:

/**
 * An annotation that indicates this member should be serialized to JSON with
 * the provided name value as its field name.
 *
 * <p>This annotation will override any {@link com.google.gson.FieldNamingPolicy}, including
 * the default field naming policy, that may have been set on the {@link com.google.gson.Gson}
 * instance.  A different naming policy can set using the {@code GsonBuilder} class.  See
 * {@link com.google.gson.GsonBuilder#setFieldNamingPolicy(com.google.gson.FieldNamingPolicy)}
 * for more information.</p>
 *
 * <p>Here is an example of how this annotation is meant to be used:</p>
 * <pre>
 * public class SomeClassWithFields {
 *   &#64SerializedName("name") private final String someField;
 *   private final String someOtherField;
 *
 *   public SomeClassWithFields(String a, String b) {
 *     this.someField = a;
 *     this.someOtherField = b;
 *   }
 * }
 * </pre>
 *
 * <p>The following shows the output that is generated when serializing an instance of the
 * above example class:</p>
 * <pre>
 * SomeClassWithFields objectToSerialize = new SomeClassWithFields("a", "b");
 * Gson gson = new Gson();
 * String jsonRepresentation = gson.toJson(objectToSerialize);
 * System.out.println(jsonRepresentation);
 *
 * ===== OUTPUT =====
 * {"name":"a","someOtherField":"b"}
 * </pre>
 *
 * <p>NOTE: The value you specify in this annotation must be a valid JSON field name.</p>
 *
 * @see com.google.gson.FieldNamingPolicy
 *
 * @author Inderjeet Singh
 * @author Joel Leitch
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface SerializedName {

  /**
   * @return the desired name of the field when it is serialized
   */
  String value();
}

這。。。。。
結(jié)合上面的getFieldName方法,Gson在獲取屬性名的時候會先判斷SerializedName注解的值,如果有就使用 SerializedName的值(value)作為屬性名。
好了,輪子造到一半讓Google給截胡了。但,省了很多事啊哈哈哈哈哈哈哈哈。

忽略上面的笑聲

好了,你的實體類的屬性現(xiàn)在應(yīng)該長這模樣,至于其他的,小伙伴們一起探索咯

@SerializedName("person_name") String name;
@SerializedName("person_age") String age;
@SerializedName("person_sex") String sex;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容