Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱
MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina.com

Gson Json 序列号 最常用的功能 MD


目录

通过 fromJson 反序列化为对象

普通对象

Person person = gson.fromJson(jsonString, Person.class);
Person person = gson.fromJson(jsonString, new TypeToken<Person>() {}.getType());

数组

String[] array = gson.fromJson(jsonString, String[].class);
String[] array = gson.fromJson(jsonString, new TypeToken<String[]>() {}.getType());
int[][] array = gson.fromJson(jsonString, int[][].class);

集合

List<Person> list = gson.fromJson(jsonString, new TypeToken<List<Person>>() {}.getType());//支持带泛型
Map<String, Integer> map = gson.fromJson(jsonString2, new TypeToken<Map<String, Integer>>() {}.getType());

问题:为何要用 TypeToken 去包装要解析的类型?为何不直接用 List<Person>.class

解疑:因为编译之后,List 和 List 这写类型的字节码文件只一个,那就是 List.class,这是Java泛型使用时要注意的问题:泛型擦除

更优雅的打印一个对象

class Fu {
protected String key = "fu";
}
class A extends Fu {
private static String NAME = "A";
private boolean isBest = true;
private int age = 28;
}
System.out.println(new Gson().toJson(new A())); //{"isBest":true,"age":28,"key":"fu"}

parse 对特殊字符串的解析

关于解析后的数据类型:

System.out.println(new JsonParser().parse("").getClass().getSimpleName());//【JsonNull】,注意不是字符串
" " -> 【JsonNull】,注意不是字符串
"null" -> 【JsonNull】,注意不是字符串 "\"\"" -> 【JsonPrimitive】,是空字符串【】
"\"null\"" -> 【JsonPrimitive】,是字符串【null】
"\"[null]\"" -> 【JsonPrimitive】,是字符串【[null]】 .parse("[]").getAsJsonArray().size();//【0】,长度为0的数组。此数组并不为null,所以解析后不必判空
.parse("[0]").getAsJsonArray().get(0).getClass().getSimpleName();//【JsonPrimitive】,有一个元素的数组
"[null]" -> 【JsonNull】,有一个元素的数组
"[{}]" -> 【JsonObject】,有一个元素的数组

注意,所有的引号、大括号、中括号都必须完整(这是一个合法的json字符串的基本要求),不然都会出现解析异常:

new JsonParser().parse("{");//End of input at line 1 column 2 path $.
new JsonParser().parse("{");//End of input at line 1 column 2 path $[0]
new JsonParser().parse("\"");//Unterminated string at line 1 column 2 path $ new JsonParser().parse("{key}");//Expected ':' at line 1 column 6 path $.key
new JsonParser().parse("1,2");//Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 3 path $

下面这些是可以的:

new JsonParser().parse("{key:value}");//这样是可以的【{"key":"value"}】,所有的引号都可以去掉
new JsonParser().parse("{key:\"value\"}"));//这样也是可以的【{"key":"value"}】
new JsonParser().parse("[0,null,\"\",{}]");

fromJson 对特殊字符串的处理

通过 Gson.fromJson 方法将一个json字符串解析为对象 AA 时,要求解析结果必须是一个JsonObject,且要求必须保证解析后的每个字段的类型和 AA 中定义的一致:

new Gson().fromJson("[]", AA.class);//Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
System.out.println(new Gson().fromJson("1", AA.class));//Expected BEGIN_OBJECT but was NUMBER at line 1 column 2 path $

但是,其可以将解析后为 JsonNull 的结果转换为 null 而不报异常:

String jString = null;
System.out.println(new Gson().fromJson(jString, AA.class));//null,注意是一个空对象,所以不能对此结果做任何操作,包括getClass
System.out.println(new Gson().fromJson(" ", AA.class));//和上述结果一样为 null

所以,解析时为了防止解析异常,在不确定数据结构的情况下,可以做一些安全性判断:

if (!TextUtils.isEmpty(response) && response.trim().startsWith("{")) {
//为了防止服务器返回数据格式错误导致解析异常
}

为某个字段提供多个属性名

或者说将 json 字符串中的某一字段的值赋给要转化的对象中的某一指定字段。比如,服务器可能通过不同的字段返回给我们错误信息,有的用tips、有的用msg、有的用errorinfo……现在,我们不管服务器用哪种方式返回给我们错误信息,我们都用 message 字段去接收。

@SerializedName(value = "message", alternate = {"tips", "msg","errorinfo","error"})
public String message;

当上面的几个属性中出现任意一个时均可以得到正确的结果,如果多种属性同时出,那么是以最后一个出现的值为准

用 JsonElement 去定义未知类型的字段

可以用Gson框架中的基类 【JsonElement】去定义json数据中不确定具体类型的某些字段。

如下面的 data ,对于不同的网络请求,其内容是完全不一样的,可能是一个JsonObject,也可能是一个JsonArray,也可能是一个String,那么就可以用一个 JsonElement 类型的字段去接收,Gson解析时不会解析具体内容,而是把此字段中的值【原封不动】的返回给你

PS:JsonElement 是 Gson 框架中所有元素的父类,其子类包括 JsonObject、JsonArray、JsonPrimitive、JsonNull。Json字符串中的所有 value 都可以被解析为 JsonElement 的子类。

public class Test {
public static void main(String[] args) {
String content1 = "{\"code\":\"100\",\"data\":{\"errorinfo\":\"成功\"}}";
String content2 = "{\"code\":\"100\",\"data\":\"成功\"}";
String content3 = "{\"code\":\"100\",\"data\":[\"成功\"]}"; System.out.println(new Gson().fromJson(content1, Response.class).data);
System.out.println(new Gson().fromJson(content2, Response.class).data);
System.out.println(new Gson().fromJson(content3, Response.class).data);
} static class Response {
public String code;
public JsonElement data;//用一个JsonElement去接收不想解析的内容
}
}

打印内容为:

{"errorinfo":"成功"}
"成功"
["成功"]
  • 拓展1,如果用 Object 去定义 data,则打印内容为:
{errorinfo=成功}
成功
[成功]

可以看到,两者被解析后的内容是不一样的,用 JsonElement 定义时得到的内容是带有双引号的完整的原始结果,而用 Object 去定义时得到的内容是被Gson框架处理后的结果

  • 拓展2,如果用一个泛型 去定义 data,比如:
static class Response<T> {
public String code;
public T data;
}

测试结果和使用 Object 时完全一致。

  • 拓展3,如果用 一个普通对象 AA 去定义 data,对于 content1,打印内容为:AA@5910e440。对于 content2、content3,直接异常!

解析 Json 字符串中的内容

注意,一定要保证 get 和 getAs* 方法获取的 key 存在且格式兼容,否则会直接崩掉!

String jsonString = "{'flag':true,'data':{'name':'张三','age':18,'address':'广州'}}";
JsonObject root = new JsonParser().parse(jsonString).getAsJsonObject(); boolean flag = root.getAsJsonPrimitive("flag").getAsBoolean();
String name = root.getAsJsonObject("data").get("name").getAsString();
System.out.println(flag + " " + name);//true 张三

格式化 Json 字符串

return new GsonBuilder()
.setPrettyPrinting()
.create()
.toJson(new JsonParser().parse(content));

将序列化后的内容写到 控制台、文件、SB中

gson.toJson(user, System.out); //直接写到控制台。System.out 继承自 PrintStream 实现了Appendable接口

FileWriter fileWriter=new FileWriter("d://a.txt");//将toJson后的字符串拼接到文件中
gson.toJson(person, fileWriter);//FileWriter 继承自 OutputStreamWriter 继承自 Writer 实现了Appendable接口
fileWriter.close(); StringBuilder builder=new StringBuilder();//将toJson后的字符串拼接到StringBuilder中
gson.toJson(person, builder);//StrngBuilder、StringBuffer都是Appendable接口的实现类
System.out.println(builder.toString());

使用 JsonWriter 编写 Json 串

JsonWriter writer = new JsonWriter(new OutputStreamWriter(System.out));//可以先写到文件中,再从文件中读取
writer.beginObject()
.name("name").value("包青天")
.name("sport").beginArray().value("篮球").value("排球").endArray()//数据
.name("info").beginObject().name("age").value(28).endObject()//对象
.endObject();
writer.close(); //{"name":"包青天","sport":["篮球","排球"],"info":{"age":28}}

写到指定位置:

StringWriter stringWriter = new StringWriter();
JsonWriter writer = new JsonWriter(stringWriter);//可以先写到文件中,再从文件中读取
writer.setIndent(" ");//设置缩进格式,一般使用2-4个空格,或使用制表符\t
//...上面的内容
System.out.println(stringWriter.getBuffer().toString());

结果

{
"name": "包青天",
"sport": [
"篮球",
"排球"
],
"info": {
"age": 28
}
}

2018-5-27

Gson Json 序列号 最常用的功能 MD的更多相关文章

  1. 12.21 Gson的常用用法 功能介绍 特点

    使用谷歌GSON常用语法: 功能:映射Java Object与json格式的数据 1.通过Annotation注解来声明 2.支持自定义属性名称 3.支持包含或排除属性 4.支持自定义接口自己完成解析 ...

  2. [.NET] 使用Json.NET提供依赖注入功能(Dependence Injection)

    [.NET] 使用Json.NET提供依赖注入功能(Dependence Injection) 前言 在一些小型项目的开发情景里,系统不需要大型DI Framework所提供的:单一对象生成.生命周期 ...

  3. GsonWithoutObject 没有对象(脱离对象) 直接提取 ... gson json

    GsonWithoutObject 脱离对象, 直接提取 package temp; import tool.FileTool; import com.google.gson.JsonElement; ...

  4. RealView编译器常用特有功能(转)

    源:RealView编译器常用特有功能 一. 关键字和运算符 1. __align(n):指示编译器在n 字节边界上对齐变量. 对于局部变量,n 值可为 1.2.4 或 8. 对于全局变量,n 可以具 ...

  5. Impala系列: Impala常用的功能函数

    --=======================查看内置的函数--=======================hive 不需要进入什么内置数据库, 即可使用 show functions 命令列出 ...

  6. iOS常用小功能

    CHENYILONG Blog 常用小功能 技术博客http://www.cnblogs.com/ChenYilong/ 新浪微博http://weibo.com/luohanchenyilong  ...

  7. Jackson Gson Json.simple 比较

    为公司做了小任务,需要用到Java Json库,Json库我几个月之前就用过,不过那时候是跟着项目来的,延续了项目的使用习惯直接用了jackson Json,而这次我觉得好好比较一下几个常见的Json ...

  8. iOS 网易彩票-6设置模块三(常用小功能)

    该篇文章中,用到很多iOS开发过程中常用的小功能,当前只是将这些功能集成到网易彩票的设置中.iOS-常用小功能介绍,请参考我的另一篇文章: iOS 常用小功能 总结:http://www.cnblog ...

  9. iOS 常用小功能 总结

    常用小功能 iOS中的很多小功能都是非常简单的,几行代码就搞定了,比如打电话.打开网址.发邮件.发短信等 打电话 方法一(不被采用): 拨号之前会弹框询问用户是否拨号,拨完后能自动回到原应用 NSUR ...

随机推荐

  1. spring RequestMapping 包含http的部分以及各部分详解

    @RequestMapping有四个参数,分别为:1.value:表示请求URL2.method:表示请求方法3.params:表示请求参数4.headers:表示请求头 [例如]:@RequestM ...

  2. gson 生成json有\u003d异常字符处理

    只需将Gson的初始化修改为 Gson gson = new GsonBuilder().disableHtmlEscaping().create(); 连接 http://blog.csdn.net ...

  3. SDOI2013 R1 Day1

    目录 2018.3.22 Test 总结 T1 BZOJ.3122.[SDOI2013]随机数生成器(BSGS 等比数列) T2 BZOJ.3123.[SDOI2013]森林(主席树 启发式合并) T ...

  4. BZOJ.2716.[Violet3]天使玩偶(CDQ分治 坐标变换)

    题目链接 考虑对于两个点a,b,距离为|x[a]-x[b]|+|y[a]-y[b]|,如果a在b的右上,那我们可以把绝对值去掉,即x[a]+y[a]-(x[b]+y[b]). 即我们要求满足x[b]& ...

  5. C#、Java、Javascript获取Unix时间戳

    背景: 因为项目需要,需要几种语言联动开发,日期字段设计的数字型 获取Unix时间戳代码: Java System.currentTimeMillis() Javascript new Date(). ...

  6. 您该选择PRINCE2 还是 PMP认证

    您该选择PRINCE2 还是 PMP认证? 很多人都问我,这是一个非常常见的问题,作为一个项目经理,他们是否应选择PRINCE2或PMP认证,因为这两个认证都是全世界非常流行的. PRINCE2 是一 ...

  7. LDO current regulator for power LED

    LDO current regulator for power LED Challenge You've got a power LED? Great! Build a flash light! Wh ...

  8. leetcode——169 Majority Element(数组中出现次数过半的元素)

    Given an array of size n, find the majority element. The majority element is the element that appear ...

  9. Delphi 局域网点对点文件传输(IdTcpClient控件)

    unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...

  10. 利用mvn deploy命令上传包(转)

    本文转自https://blog.csdn.net/chenaini119/article/details/52764543 mvn安装 下载maven的bin,在apache官方网站可以下载. ht ...