Gson Json 序列号 最常用的功能 MD
Markdown版本笔记 | 我的GitHub首页 | 我的博客 | 我的微信 | 我的邮箱 |
---|---|---|---|---|
MyAndroidBlogs | baiqiantao | baiqiantao | bqt20094 | baiqiantao@sina.com |
Gson Json 序列号 最常用的功能 MD
目录
通过 fromJson 反序列化为对象
更优雅的打印一个对象
parse 对特殊字符串的解析
fromJson 对特殊字符串的处理
为某个字段提供多个属性名
用 JsonElement 去定义未知类型的字段
解析 Json 字符串中的内容
格式化 Json 字符串
将序列化后的内容写到 控制台、文件、SB中
使用 JsonWriter 编写 Json 串
通过 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的更多相关文章
- 12.21 Gson的常用用法 功能介绍 特点
使用谷歌GSON常用语法: 功能:映射Java Object与json格式的数据 1.通过Annotation注解来声明 2.支持自定义属性名称 3.支持包含或排除属性 4.支持自定义接口自己完成解析 ...
- [.NET] 使用Json.NET提供依赖注入功能(Dependence Injection)
[.NET] 使用Json.NET提供依赖注入功能(Dependence Injection) 前言 在一些小型项目的开发情景里,系统不需要大型DI Framework所提供的:单一对象生成.生命周期 ...
- GsonWithoutObject 没有对象(脱离对象) 直接提取 ... gson json
GsonWithoutObject 脱离对象, 直接提取 package temp; import tool.FileTool; import com.google.gson.JsonElement; ...
- RealView编译器常用特有功能(转)
源:RealView编译器常用特有功能 一. 关键字和运算符 1. __align(n):指示编译器在n 字节边界上对齐变量. 对于局部变量,n 值可为 1.2.4 或 8. 对于全局变量,n 可以具 ...
- Impala系列: Impala常用的功能函数
--=======================查看内置的函数--=======================hive 不需要进入什么内置数据库, 即可使用 show functions 命令列出 ...
- iOS常用小功能
CHENYILONG Blog 常用小功能 技术博客http://www.cnblogs.com/ChenYilong/ 新浪微博http://weibo.com/luohanchenyilong ...
- Jackson Gson Json.simple 比较
为公司做了小任务,需要用到Java Json库,Json库我几个月之前就用过,不过那时候是跟着项目来的,延续了项目的使用习惯直接用了jackson Json,而这次我觉得好好比较一下几个常见的Json ...
- iOS 网易彩票-6设置模块三(常用小功能)
该篇文章中,用到很多iOS开发过程中常用的小功能,当前只是将这些功能集成到网易彩票的设置中.iOS-常用小功能介绍,请参考我的另一篇文章: iOS 常用小功能 总结:http://www.cnblog ...
- iOS 常用小功能 总结
常用小功能 iOS中的很多小功能都是非常简单的,几行代码就搞定了,比如打电话.打开网址.发邮件.发短信等 打电话 方法一(不被采用): 拨号之前会弹框询问用户是否拨号,拨完后能自动回到原应用 NSUR ...
随机推荐
- JAVA JMX协议监控
JMX协议监控,可通过JMX协议远程监控,实时监控线上jvm情况,并通过平台管理界面进行 展示,可以通过监控实时获得线上服务器运行情况. 可以监控内存.实时线程.共享内存等各种信息. 获取实时线程信息 ...
- android 滑动冲突
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha 通过move事件的 拦截. 在滑动组件中,重写 在拦截触摸事件的时候 这个方法, 然后 ...
- HDU 5907 Find Q dp
Find Q 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5907 Description Byteasar is addicted to the ...
- CF 222 (DIV 1)
A: 我是bfs出一颗树,然后删掉树后面的k个结点. 其实也可以直接bfs出一块连通的s - k个点,其余的.打X就可以了. 很水的题目. /* *************************** ...
- 怎么发现RAC环境中'library cache pin'等待事件的堵塞者(Blocker)?
怎么发现RAC环境中的'library cache pin'等待事件的堵塞者(Blocker) 參考自 How to Find the Blocker of the 'library cache pi ...
- HTML一些标签注意事项
最近在IE10下运行一个以前的做web系统发现了两个小问题: 一.图片上使用"alt"属性来添加一些文字提示信息在IE10下无法正常显示出来 上网查了一下原因:原来是现在一些较新的 ...
- Opencv2教程一:图像变换之阈值二值threshold
网名:无名 QQ:16349023 email:mengwzy@qq.com 曾经非常少写教程,写的可能有点乱希望大对家有帮助 threshold 方法是通过遍历灰度图中点.将图像信息二值化,处理 ...
- 在ASP.NET MVC下限制同一个IP地址单位时间间隔内的请求次数
有时候,当用户请求一个Controller下的Action,我们希望,在单位时间间隔内,比如每秒,每分钟,每小时,每天,每星期,限制同一个IP地址对某个Action的请求次数.如何做呢? stefan ...
- 【GitLab】【GitHub】GitLab和GitHub的双向同步
有这种需求,需要GitLab上的现有代码库,同步到GitHub上. 又有一种需求,需要将GitHub上的代码库,同步到gitlab上. 一.GitLab上的代码库,自动同步到GitHub上 大致需要三 ...
- Universal-Image-Loader解析(三)——用ListView和ViewPager加载网络中的图片
现在我们终于可以通过这个框架来实现ListView中加载图片了,至于ViewPager还是别的,原理其实都是一样的 一.ListView 1.布局文件 list_layout.xml & ...