导航:首页 > 编程语言 > json解析long格式数据类型

json解析long格式数据类型

发布时间:2025-02-12 14:57:02

json数据可以为什么类型

从结构上看,所有来的数据(自data)最终都可以分解成三种类型:
第一种类型是标量(scalar),也就是一个单独的字符串(string)或数字(numbers),比如"北京"这个单独的词。
第二种类型是序列(sequence),也就是若干个相关的数据按照一定顺序并列在一起,又叫做数组(array)或列表(List),比如"北京,上海"。
第三种类型是映射(mapping),也就是一个名/值对(Name/value),即数据有一个名称,还有一个与之相对应的值,这又称作散列(hash)或字典(dictionary),比如"首都:北京"。
Json的规格非常简单,只用一个页面几百个字就能说清楚,而且Douglas Crockford声称这个规格永远不必升级,因为该规定的都规定了。
1) 并列的数据之间用逗号(", ")分隔。
2) 映射用冒号(": ")表示。
3) 并列数据的集合(数组)用方括号("[]")表示。
4) 映射的集合(对象)用大括号("{}")表示。

② 如何编写一个JSON解析器

编写一个JSON解析器实际上就是一个函数,它的输入是一个表示JSON的字符串,输出是结构化的对应到语言本身的数据结构。

和XML相比,JSON本身结构非常简单,并且仅有几种数据类型,以Java为例,对应的数据结构是:

"string":Java的String;
number:Java的Long或Double;
true/false:Java的Boolean;
null:Java的null;
[array]:Java的List<Object>或Object[];
{"key":"value"}:Java的Map<String, Object>。

解析JSON和解析XML类似,最终都是解析为内存的一个对象。出于效率考虑,使用流的方式几乎是唯一选择,也就是解析器只从头扫描一遍JSON字符串,就完整地解析出对应的数据结构。

本质上解析器就是一个状态机,只要按照JSON定义的格式(参考http://www.json.org,正确实现状态转移即可。但是为了简化代码,我们也没必要完整地实现一个字符一个字符的状态转移。

解析器的输入应该是一个字符流,所以,第一步是获得Reader,以便能不断地读入下一个字符。

在解析的过程中,我们经常要根据下一个字符来决定状态跳转,此时又涉及到回退的问题,就是某些时候不能用next()取下一个字符,而是用peek()取下一个字符,但字符流的指针不移动。所以,Reader接口不能满足这个需求,应当进一步封装一个CharReader,它可以实现:

char next():读取下一个字符,移动Reader指针;
char peek():读取下一个字符,不移动Reader指针;
String next(int size):读取指定的N个字符并移动指针;
boolean hasMore():判断流是否结束。

JSON解析比其他文本解析要简单的地方在于,任何JSON数据类型,只需要根据下一个字符即可确定,仔细总结可以发现,如果peek()返回的字符是某个字符,就可以期望读取的数据类型:

{:期待一个JSON object;
::期待一个JSON object的value;
,:期待一个JSON object的下一组key-value,或者一个JSON array的下一个元素;
[:期待一个JSON array;
t:期待一个true;
f:期待一个false;
n:期待一个null;
":期待一个string;
0~9:期待一个number。

但是单个字符要匹配的状态太多了,需要进一步把字符流变为Token,可以总结出如下几种Token:

END_DOCUMENT:JSON文档结束;
BEGIN_OBJECT:开始一个JSON object;
END_OBJECT:结束一个JSON object;
BEGIN_ARRAY:开始一个JSON array;
END_ARRAY:结束一个JSON array;
SEP_COLON:读取一个冒号;
SEP_COMMA:读取一个逗号;
STRING:一个String;
BOOLEAN:一个true或false;
NUMBER:一个number;
NULL:一个null。

然后,将CharReader进一步封装为TokenReader,提供以下接口:

Token readNextToken():读取下一个Token;
boolean readBoolean():读取一个boolean;
Number readNumber():读取一个number;
String readString():读取一个string;
void readNull():读取一个null。

由于JSON的Object和Array可以嵌套,在读取过程中,使用一个栈来存储Object和Array是必须的。每当我们读到一个BEGIN_OBJECT时,就创建一个Map并压栈;每当读到一个BEGIN_ARRAY时,就创建一个List并压栈;每当读到一个END_OBJECT和END_ARRAY时,就弹出栈顶元素,并根据新的栈顶元素判断是否压栈。此外,读到Object的Key也必须压栈,读到后面的Value后将Key-Value压入栈顶的Map。

如果读到END_DOCUMENT时,栈恰好只剩下一个元素,则读取正确,将该元素返回,读取结束。如果栈剩下不止一个元素,则JSON文档格式不正确。

最后,JsonReader的核心解析代码parse()就是负责从TokenReader中不断读取Token,根据当前状态操作,然后设定下一个Token期望的状态,如果与期望状态不符,则JSON的格式无效。起始状态被设定为STATUS_EXPECT_SINGLE_VALUE | STATUS_EXPECT_BEGIN_OBJECT | STATUS_EXPECT_BEGIN_ARRAY,即期望读取到单个value、{或[。循环的退出点是读取到END_DOCUMENT时。

③ 问题复盘|在使用 gson 时,数字被自动转为 double 类型

在使用Gson进行数据转换时,遇到数字自动转为double类型的问题。将一个JsonObject转换为Map后,数字全部变为double形式,年龄2变为2.0,身高98.2正常显示,但登记时间显示为1.694533284627E12。面对此问题,我首先尝试通过搜索引擎寻找解决方案。发现Gson默认将number类型数据解析为double类型,并指出此问题在版本2.8.9中已修复。我查看自己使用的Gson版本为2.8.6,低于2.8.9,且存在相同问题。问题定位后,解决方法较为直接:升级Gson版本至2.8.9,并在创建Gson对象时手动设置数字类型转换策略。完成这些步骤后,问题得到解决。总结,此问题并非首次出现,也难以避免再次发生,简单记录,等待有缘人参考。

阅读全文

与json解析long格式数据类型相关的资料

热点内容
网络评论有什么好处 浏览:191
千寻位置踩的点在哪个文件夹 浏览:298
自学大数据从哪里学习 浏览:10
iphone4s百度输入法 浏览:192
一级文件夹 浏览:832
iphone九宫格输入法调不出 浏览:626
win10阅读器pdf打不开 浏览:22
三年级下册数据统计你有哪些建议 浏览:375
可视化中文编程哪个软件好 浏览:163
wordpress标签热门 浏览:641
什么是医学常规数据 浏览:367
win10下载的主题图片在哪里 浏览:918
中控考勤机通用密码 浏览:774
侠客win10安装不了驱动 浏览:662
桌面文件里的excel表格打不开 浏览:305
如何拒绝编程老师 浏览:24
linux查看文件后缀 浏览:608
u盘变小了文件也没了 浏览:433
技能证在什么网站查询 浏览:945
数控编程代码q是什么意思 浏览:17

友情链接