End

Gson 基本使用 解析、生成、映射

本文地址


目录

Gson 基本使用 解析、生成、映射

解析和生成

Gson提供了 fromJson()toJson() 两个用于解析和生成的方法,前者实现反序列化,后者实现了序列化。

基本数据类型

Gson gson = new Gson();
int i = gson.fromJson("100", Integer.class);       // 100
boolean b = gson.fromJson("true", Boolean.class);  // true
String str = gson.fromJson("包青天", String.class); // 包青天

String jsonNumber = gson.toJson(i);   // 100
String jsonBoolean = gson.toJson(b);  // true
String jsonString = gson.toJson(str); // 包青天

POJO 类

String jsonString = "{\"name\":\"包青天\",\"age\":24}";
User user = gson.fromJson(jsonString, User.class);

User user2 = new User("包青天", 24);
String jsonObject2 = gson.toJson(user2); // {"name":"包青天","age":24}

数组和集合

通过 Gson 解析 jsonArray 时,一般有两种方式:使用数组,或使用 List。

数组比较简单:

String jsonArray = "[\"Android\",\"Java\",\"PHP\"]";
String[] strings = gson.fromJson(jsonArray, String[].class);

String[] strings2 = {"Android", "Java", "PHP"};
String jsonArray2 = gson.toJson(strings2);

但对于 List,将上面的代码中的 String[].class 直接改为 List<String>.class 是行不通的,因为对于 Java 来说,List<String>List<User> 这两个的字节码文件是一个,那就是 List.class,这是 Java 泛型使用时要注意的问题:泛型擦除

为了解决的上面的问题,Gson 为我们提供了 TypeToken 来实现对泛型的支持。

String jsonArray = "[\"Android\",\"Java\",\"PHP\"]";
List<String> list = gson.fromJson(jsonArray, new TypeToken<List<String>>() {}.getType());

注意:上面的类型是 new TypeToken<List<String>>() {}.getType(),而不是 new TypeToken<List<String>>().getType()

属性映射

从上面 POJO 的生成与解析可以看出,JSON 串中的 key 和 JavaBean 中的 field 是完全一致的,如果不一致时该怎么办呢?

注解 @SerializedName

Gson 在序列化和反序列化时需要使用反射,说到反射就不得不想到注解。一般各类库都将注解放到annotations包下,打开源码果然有一个annotations,里面有一个SerializedName的注解类,这就是我们要找的。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD })
public @interface SerializedName {
    String value(); //方法名为value()的属性不需要指定key
    String[] alternate() default {}; //默认为空
}

映射

通过此注解,便可以将服务端返回的任意 key 的值映射到指定的 field 上,例如:

@SerializedName("email_address")
public String emailAddress;

此注解提供了两个属性,上面用到了其中一个,另外还有一个属性alternate,接收一个数组,上述案例的完整表达形式为:

@SerializedName(value = "emailAddress", alternate = {"email_address"})
public String emailAddress;

此时,无论 key 是 emailAddress 还是 email_address,都会映射到指定的 field 上。

多键映射

  • 当与属性 value 的值或集合 alternate 中任意一个元素的值匹配时,均可正确映射到指定的 field 上
  • 当多种情况同时出时,以 json 字符串中最后一个出现的值为准
String jsonString = "{\"emailAddress\":\"emailAddress\",\"email_address\":\"email_address\",\"email\":\"email\"}";
System.out.println(new Gson().fromJson(jsonString, User.class).emailAddress);
  • 没有指定注解 @SerializedName 时:emailAddress
  • 指定注解 @SerializedName("email_address") 时:email_address
  • 指定注解 @SerializedName(value = "emailAddress", alternate = {"email", "email_address"}) 时:email
  • 指定注解 @SerializedName(value = "emailAddress", alternate = {"email_address", "email"}) 时:email

2017-09-12

posted @ 2017-09-12 14:36  白乾涛  阅读(881)  评论(0编辑  收藏  举报