Gson 简略应用姿态小结

对于 Json 序列化的框架能够说比拟多了,比方 Spring 默认的 Jackson,国内互联网用的比拟多的 FastJson,本文则次要介绍一下 Gson 的简略应用姿态,并不会波及到不同的 json 框架的性能比照

本文次要内容来源于官网教程: https://github.com/google/gson/blob/master/UserGuide.md

<!-- more -->

1. 依赖导入

首先咱们借助 maven 来引入依赖包,依照本人的理论状况抉择一个版本(简略的应用姿态与具体的版本并没有太大的关联性)

<groupId>com.google.code.gson</groupId><artifactId>gson</artifactId>

2. 根本的序列化与反序列化

一般来讲,咱们通过 Gson 对象来实现 Json 的序列化与反序列化,如下是几个简略的序列化与反序列化的 case

// SerializationGson gson = new Gson();gson.toJson(1);            // ==> 1gson.toJson("abcd");       // ==> "abcd"gson.toJson(new Long(10)); // ==> 10int[] values = { 1 };gson.toJson(values);       // ==> [1]// Deserializationint one = gson.fromJson("1", int.class);Integer one = gson.fromJson("1", Integer.class);Long one = gson.fromJson("1", Long.class);Boolean false = gson.fromJson("false", Boolean.class);String str = gson.fromJson("\"abc\"", String.class);String[] anotherStr = gson.fromJson("[\"abc\"]", String[].class);

下面的 case 中,次要就是借助gson.toJson来输入 Json 字符串,借助gson.fromJson返序列化失去对象

3. 对象序列化

对象的序列化与反序列化能够说是最常见的,在 Gson 的应用过程中,举荐的对象写法

  • filed:private 润饰
  • 不心愿序列化的成员,增加transient修饰符
  • 默认无参构造方法(可选,这里跟人举荐保留,不同于 FastJson 的必须存在)
public static class BaseBean {    private int age;    private String name;    private transient int code;    private String email;    public BaseBean() {    }    @Override    public String toString() {        return "BaseBean{" + "age=" + age + ", name='" + name + '\'' + ", code=" + code + ", email='" + email +                '\'' + '}';    }}@Testpublic void testObjGson() {    BaseBean bean = new BaseBean();    bean.age = 10;    bean.code = 20;    bean.name = "一灰灰blog";    Gson gson = new Gson();    String str = gson.toJson(bean);    System.out.println("json str: " + str);    BaseBean out = gson.fromJson(str, BaseBean.class);    System.out.println("after deserialization: " + out);}

下面的应用姿态和后面并没有什么实质的区别,接下来看一下输入后果

json str: {"age":10,"name":"一灰灰blog"}after deserialization: BaseBean{age=10, name='一灰灰blog', code=0, email='null'}

请留神:

  • 输入 json 串时,null 和transient润饰的成员不会输入到 json 串中
  • 对象没有 Get/Set 办法,也仍然能够反序列化(对象也没有继承自 Serialize 接口,当然我集体的观点是请继承 Serialize 接口)

如果我心愿将 null 的成员,也能够输入到 json 串,能够如下操作

// 并不间接创立Gson对象,改用GsonBuilderGson gsonWithNUll = new GsonBuilder().serializeNulls().create();System.out.println("serialize with null: " + gsonWithNUll.toJson(bean));

输入后果如下

serialize with null: {"age":10,"name":"一灰灰blog","email":null}

阐明:如果心愿扩大序列化形式,通过 GsonBuilder 来构建 Gson 对象是一个不错的抉择

4. JsonObject 与 JsonArray

某些场景下咱们可能并没有定义反序列化的数据对象,比方 FastJson 中的间接反序列化为JSONObject/JSONArray,而后手动获取数据进行业务解决,这种场景下,gson 能够如何反对呢?

Map map = new HashMap();map.put("a", "hello world");map.put(12, true);map.put("array", Arrays.asList("a", "c", "f", 12));map.put("obj", Maps.newHashMap("k", "v"));Gson gson = new Gson();String str = gson.toJson(map);// 间接借助 JsonParser#parseString 来实现反序列化JsonObject obj = JsonParser.parseString(str).getAsJsonObject();String a = obj.get("a").getAsString();boolean b = obj.get("12").getAsBoolean();JsonArray ary = obj.get("array").getAsJsonArray();JsonObject o = obj.get("obj").getAsJsonObject();System.out.println("a:" + a + " b:" + b + " ary:" + ary + " o:" + o);

请留神,咱们这里次要借助的是JsonParser.parseString办法,输出参数能够是 String 也能够是流,返回的是JsonElement对象,这个对象比拟有意思,提供了一些根底的类型输入办法如

  • getAsString: 返回 String
  • getAsInt: 返回 int
  • getAsJsonArray: 返回 JsonArray(json 数组)
  • getAsJsonObject: 返回 JsonObject (Json 对象)
  • ...

5. 泛型序列化

以上属于惯例的根本应用姿态,理论的工作中,对于泛型的序列化和反序列化能够说十分常见了,那么应该如何解决呢

public static class ResWrapper<T> {    private T data;    private int code;    private String msg;}public static class User {    private int age;    private String name;}@Testpublic void testGenri() {    ResWrapper<User> wrapper = new ResWrapper<>();    wrapper.code = 0;    wrapper.msg = "name";    User user = new User();    user.age = 18;    user.name = "一灰灰";    wrapper.data = user;    Gson gson = new Gson();    String str = gson.toJson(wrapper);    Type type = new TypeToken<ResWrapper<User>>() {}.getType();    ResWrapper<User> out = gson.fromJson(str, type);    System.out.println(out);}

下面的外围在于 Type 的生成: new TypeToken<ResWrapper<User>>() {}.getType();

6. 进阶

以上内容基本上能够笼罩日常业务开发中 90%的场景,当然 gson 也反对一些更高级的性能

如 filed name 映射

  • @SerializedName("custom_naming")
private class SomeObject {  @SerializedName("custom_naming")  private final String someField;  private final String someOtherField;  public SomeObject(String a, String b) {    this.someField = a;    this.someOtherField = b;  }}

如版本反对

  • @Since(1.1)
public class VersionedClass {  @Since(1.1) private final String newerField;  @Since(1.0) private final String newField;  private final String field;  public VersionedClass() {    this.newerField = "newer";    this.newField = "new";    this.field = "old";  }}VersionedClass versionedObject = new VersionedClass();Gson gson = new GsonBuilder().setVersion(1.0).create();String jsonOutput = gson.toJson(versionedObject);System.out.println(jsonOutput);System.out.println(); // 输入: {"newField":"new","field":"old"}gson = new Gson();jsonOutput = gson.toJson(versionedObject);System.out.println(jsonOutput); // 输入: {"newerField":"newer","newField":"new","field":"old"}

自定义的类型转换

GsonBuilder gson = new GsonBuilder();gson.registerTypeAdapter(MyType.class, new DateTimeSerializer());gson.registerTypeAdapter(MyType.class, new DateTimeDeserializer());private class DateTimeSerializer implements JsonSerializer<DateTime> {  public JsonElement serialize(DateTime src, Type typeOfSrc, JsonSerializationContext context) {    return new JsonPrimitive(src.toString());  }}private class DateTimeDeserializer implements JsonDeserializer<DateTime> {  public DateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)      throws JsonParseException {    return new DateTime(json.getAsJsonPrimitive().getAsString());  }}

可视化的 json 输入

Gson gson = new GsonBuilder().setPrettyPrinting().create();String jsonOutput = gson.toJson(someObject);

II. 其余

1. 一灰灰 Blog: https://liuyueyi.github.io/he...

一灰灰的集体博客,记录所有学习和工作中的博文,欢送大家前去逛逛

2. 申明

尽信书则不如,以上内容,纯属一家之言,因集体能力无限,不免有疏漏和谬误之处,如发现 bug 或者有更好的倡议,欢送批评指正,不吝感谢

  • 微博地址: 小灰灰 Blog
  • QQ: 一灰灰/3302797840

3. 扫描关注

一灰灰 blog