Gson 简单使用姿势小结

简介: 关于 Json 序列化的框架可以说比较多了,比如 Spring 默认的 Jackson,国内互联网用的比较多的 FastJson,本文则主要介绍一下 Gson 的简单使用姿势,并不会涉及到不同的 json 框架的性能对比

关于 Json 序列化的框架可以说比较多了,比如 Spring 默认的 Jackson,国内互联网用的比较多的 FastJson,本文则主要介绍一下 Gson 的简单使用姿势,并不会涉及到不同的 json 框架的性能对比


本文主要内容来源于官方教程: github.com/google/gson…


1. 依赖导入



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


<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
复制代码


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



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


// 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 的必须存在)
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);
}
复制代码


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


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对象,改用GsonBuilder
Gson 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 对象)
  • ...

image.png


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;
}
@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);
}
复制代码

image.png


上面的核心在于 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);



相关文章
|
运维 Cloud Native 前端开发
如何解决 503 Service Temporarily Unavailable?
如何解决 503 Service Temporarily Unavailable?
3509 0
|
网络协议
轨迹系列——Socket总结及实现基于TCP或UDP的809协议方法
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 在上一篇博客中我详细介绍了809协议的内容。809协议规范了通信的报文,通信的规则等,但是并没限制通信使用的传输协议。
3032 0
|
存储 数据可视化 数据挖掘
基于大数据的电影可视化、推荐与票房预测系统
本系统基于Python与Flask框架,结合Echarts等技术,实现电影数据的采集、存储与可视化展示。通过对票房、评分、评论等数据的分析,生成图表与词云,帮助用户直观理解电影市场趋势,支持决策制定与观影推荐,提升电影行业的数据分析能力与用户体验。
|
存储 算法 安全
Java中的对称加密算法的原理与实现
本文详细解析了Java中三种常用对称加密算法(AES、DES、3DES)的实现原理及应用。对称加密使用相同密钥进行加解密,适合数据安全传输与存储。AES作为现代标准,支持128/192/256位密钥,安全性高;DES采用56位密钥,现已不够安全;3DES通过三重加密增强安全性,但性能较低。文章提供了各算法的具体Java代码示例,便于快速上手实现加密解密操作,帮助用户根据需求选择合适的加密方案保护数据安全。
972 58
|
IDE Java Maven
排查maven 冲突及解决方式
【9月更文挑战第25天】在开发过程中,Maven 冲突可能导致多种问题。本文介绍排查方法:查看错误日志中的提示信息;使用 `mvn dependency:tree` 命令检查依赖树;利用 IDE 工具进行依赖分析。解决冲突的方式包括:排除依赖、手动指定版本、更新依赖以及使用 Maven 插件如 Maven Enforcer Plugin 强制依赖一致性。处理时需确保项目稳定与兼容。
1898 2
|
缓存 NoSQL Linux
入职必会-开发环境搭建26-Redis下载和安装
Redis是一个开源的、内存中的数据结构存储系统,用作数据库、缓存、消息中间件。它提供了丰富的数据结构,包括字符串、哈希、列表、集合、有序集合、位图、HyperLogLog、地理空间索引和流。以下是 Redis 的一些主要特点和用途。
601 0
|
监控 小程序 Java
《优化接口设计的思路》系列:第五篇—接口发生异常如何统一处理
大家好!我是sum墨,一个一线的底层码农,平时喜欢研究和思考一些技术相关的问题并整理成文,限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。
1340 0
《优化接口设计的思路》系列:第五篇—接口发生异常如何统一处理
|
JavaScript 测试技术 iOS开发
vue element plus Icon 图标
vue element plus Icon 图标
8171 0
|
NoSQL JavaScript 前端开发
Spring Boot3.0升级,踩坑之旅,附解决方案(二)
Spring Boot3.0升级,踩坑之旅,附解决方案(二)
1195 1
|
Java
Springboot加载动态Bean的10种方式
Springboot加载动态Bean的10种方式
1408 0

热门文章

最新文章