200826-Gson 简单使用姿势小结

文章目录
  1. 1. 依赖导入
  2. 2. 基本的序列化与反序列化
  3. 3. 对象序列化
  4. 4. JsonObject与JsonArray
  5. 5. 泛型序列化
  6. 6. 进阶
  • II. 其他
    1. 1. 一灰灰Blog: https://liuyueyi.github.io/hexblog
    2. 2. 声明
    3. 3. 扫描关注
  • 关于Json序列化的框架可以说比较多了,比如Spring默认的Jackson,国内互联网用的比较多的FastJson,本文则主要介绍一下Gson的简单使用姿势,并不会涉及到不同的json框架的性能对比

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

    1. 依赖导入

    首先我们借助maven来引入依赖包,按照自己的实际情况选择一个版本(简单的使用姿势与具体的版本并没有太大的关联性)

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

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    // Serialization
    Gson gson = new Gson();
    gson.toJson(1); // ==> 1
    gson.toJson("abcd"); // ==> "abcd"
    gson.toJson(new Long(10)); // ==> 10
    int[] values = { 1 };
    gson.toJson(values); // ==> [1]

    // Deserialization
    int 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的必须存在)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    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 +
    '\'' + '}';
    }
    }
    @Test
    public 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);
    }

    上面的使用姿势和前面并没有什么本质的区别,接下来看一下输出结果

    1
    2
    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串,可以如下操作

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

    输出结果如下

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

    说明:如果希望扩展序列化方式,通过GsonBuilder来构建Gson对象是一个不错的选择

    4. JsonObject与JsonArray

    某些场景下我们可能并没有定义反序列化的数据对象,比如FastJson中的直接反序列化为JSONObject/JSONArray,然后手动获取数据进行业务处理,这种场景下,gson可以如何支持呢?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    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. 泛型序列化

    以上属于常规的基本使用姿势,实际的工作中,关于泛型的序列化和反序列化可以说非常常见了,那么应该如何处理呢

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    public static class ResWrapper<T> {
    private T data;
    private int code;
    private String msg;
    }

    public static class User {
    private int age;
    private String name;
    }

    @Test
    public 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")
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    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"}

    自定义的类型转换

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    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输出

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

    II. 其他

    1. 一灰灰Bloghttps://liuyueyi.github.io/hexblog

    一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛

    2. 声明

    尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激

    3. 扫描关注

    一灰灰blog

    QrCode

    # Gson

    评论

    Your browser is out-of-date!

    Update your browser to view this website correctly. Update my browser now

    ×