利用FastJson,拼接复杂嵌套json数据&&直接从json字符串中(不依赖实体类)解析出键值对
1.拼接复杂嵌套json
FastJson工具包中有两主要的类: JSONObject和JSONArray ,前者表示json对象,后者表示json数组。他们两者都能添加Object类型的对象,但是JSONArray没有put()方法,只有add()方法。这与json数组的定义有关,json数组只能添加元素,而不能添加键值对。而JSONObject因为是一个对象,不能容纳其他对象,不能添加对象,没有add() 方法,它就只有put()方法来添加键值对。JSONObject和JSONArray 似乎只能两选一,要么用JSONObject的put()方法添加一个键值对,或使用JSONArray的add()方法添加一个元素。实际上是可以两者兼顾的,JSONObect的put(String key,Object value)方法中值参数value是Object类型,那么这个数据类型也就可以是JSONArray类型。这样的话,就可以在json对象中添加json数组中,从而轻松地拼接复杂的嵌套型的son数据。
如果要返回如下格式的json数据,常规的手工拼接将非常难以实现,且容易出错。
1).首先从最内层开始分析,最内层是两个json对象,{item": "目录管理","url": "/system/menu/toMain"},这个json对象有相应的实体类AdminMenu,而外层是一个json数组将这两个对象包含进去。
AdminMenu menu1 = new AdminMenu();
menu1.setUrl("/system/menu/toMain");
menu1.setName("目录管理");//通过"getItem(){ return name}",所以只设置setName即可 AdminMenu menu2 = new AdminMenu();
menu2.setUrl("/system/user/toMain");
menu2.setName("用户管理"); JSONArray level2Array = new JSONArray();
//将两个实体类添加一json数据中,FastJson会将实体类自动转为json对象
level2Array.add(menu1);
level2Array.add(menu2);
2).然后分析Level2(json数据)和Level1(键值对)又是一个匿名json对象的两个属性,把这两个属性添加到json对象中。
JSONObject menuInfoElement = new JSONObject();
menuInfoElement.put("Level2", level2Array);
menuInfoElement.put("Level1", "系统管理");
3)再然后分析那个匿名json对象menuInfoElement是json数组menuInfo的唯一的一个元素,那么将匿名json对象menuInfoElement添加到menuInfo数组中。
JSONArray menuInfoArray = new JSONArray();
menuInfoArray.add(menuInfoElement);
4)再分析,menuInfo是json对象content的一个属性
JSONObject contentObj = new JSONObject();
contentObj.put("menuInfo", menuInfoArray);
5)最终,将'status' 'content' 'message'作为最终返回的json对象的属性
JSONObject jsonMainObj = new JSONObject();
jsonMainObj.put("status", "success");
jsonMainObj.put("message", "查询成功");
jsonMainObj.put("content", contentObj);
测试代码
@Test
public void testJson1()
{
AdminMenu menu1 = new AdminMenu();
menu1.setUrl("/system/menu/toMain");
menu1.setName("目录管理");//通过"getItem(){ return name}",所以只设置setName即可 AdminMenu menu2 = new AdminMenu();
menu2.setUrl("/system/user/toMain");
menu2.setName("用户管理"); JSONArray level2Array = new JSONArray();
//将两个实体类添加一json数据中,FastJson会将实体类自动转为json对象
level2Array.add(menu1);
level2Array.add(menu2); JSONObject menuInfoElement = new JSONObject();
menuInfoElement.put("Level2", level2Array);
menuInfoElement.put("Level1", "系统管理"); JSONArray menuInfoArray = new JSONArray();
menuInfoArray.add(menuInfoElement); JSONObject contentObj = new JSONObject();
contentObj.put("menuInfo", menuInfoArray); JSONObject jsonMainObj = new JSONObject();
jsonMainObj.put("status", "success");
jsonMainObj.put("message", "查询成功");
jsonMainObj.put("content", contentObj); System.out.println(jsonMainObj.toJSONString());
}
输出的字符串
{"message":"查询成功",
"content":{"menuInfo":[{"Level2":[{"item":"目录管理","name":"目录管理","url":"/system/menu/toMain"},
{"item":"用户管理","name":"用户管理","url":"/system/user/toMain"}],
"Level1":"系统管理"}]},
"status":"success"}
2.不依赖实体类,直接从json格式字符串中解析出键值对
JSONObject 有 parseObject(String text, Class<T> clazz) 静态方法,将json字符串解析成T类型的java对象;而 JSONArray也有parseArray(String text, Class<T> clazz) 将json字符串解析成List<T>的集合对象。
但它们都需要传入一个Class对象作为参数,换句话说,必须先有一个Class对应的实体类,而很多时候我们只会将其中的键值对解析出来用一次,只临时使用它一次就去创建一个新的实体类,将会导致类爆炸。
换种思路,JSONArray.parseArray(String text)将返回一个JSONArray对象。根据其add(Object obj)的方法入参类型是Object,那么其元素类型可能是一个实体类也可能是一个普通的json对象JSONObject,。但当前我们调用parseArray(String text)静态方法传入了的一个json字符串,以此构建出一个json数组,那么可以肯定其内部的元素类型一定是JSONObject,因此将其中的每个元素从Object强制转换为JSONObject类型,然后再从每个JSONObject取出键值对。
@Test
public void parseJsonText()
{
String menuList = "[{'id':1,'locked':false,'loginedTime':'2014-01-21'},"
+ "{'id':2,'locked':true,'loginedTime':'2015-03-22'},]";
/*
* 有属性名与之对应的User类,则可以写成这种形式,但目前并不存在User类,
* 所以无法实现 List<User> uList=JSONArray.parseArray(menuList, User.class);
*/
JSONArray jUsers = JSONArray.parseArray(menuList);
/**
* 这个for循环也可以
* for(int i=0;i<jUsers.size();i++){
JSONObject user=jUsers.getJSONObject(i);
}
*/
for (Object userObj : jUsers)
{
JSONObject jUser = (JSONObject)userObj; // 强制类型转换,因为知道其元素的具体类型是JSONObject,那么就不会出错
/**
* {'id':1}键值对的值1没加引号,FastJson认为它是数字,
* 如果是{'id':'1'}格式,FastJson认为它是字符串,转换为Integer将出错
*/
Integer id = (Integer)jUser.get("id");
/*
* {'locked':false}键值对的值没加引号,FastJson视作boolean类型,
* 如果是{'locked':'false'}格式,FastJson视作String类型,强制转换为boolean将运行时出错
*
*/
boolean locked = (boolean)jUser.get("locked");
String loginTime = (String)jUser.get("loginedTime");
System.out.println("用户id:" + id + " ,锁定了吗? " + locked + " 登录时间:" + loginTime);
}
}
结果输出
另外需要注意,前端语言JavaScript是弱类型语言,它可以根据变量具体的值去推断其类型,而JAVA是强类型语言,对字符串和数字有着明确的区分。
前端的{'id',23}和{'id','23'}没有区别,但FastJson解析对这两种格式有明显的不同,前者键值对没有引号的值(23)视为数字,后者键值对有引号的值('23')视作字符串。
@Test
public void parseJsonError()
{
String menuList = "[{'id':1,'locked':false,'loginedTime':'2014-01-21'},"
+ "{'id':2,'locked':true,'loginedTime':'2015-03-22'},]"; JSONArray jUsers = JSONArray.parseArray(menuList);
try{
for (Object userObj : jUsers)
{
JSONObject jUser = (JSONObject)userObj; // 强制类型转换,因为知道其元素的具体类型是JSONObject,那么就不会出错 String id = (String)jUser.get("id");//将出错 String locked = (String)jUser.get("locked");//将出错
String loginTime = (String)jUser.get("loginedTime");
System.out.println("用户id:" + id + " ,锁定了吗? " + locked + " 登录时间:" + loginTime);
}
}catch(Exception e){
e.printStackTrace();
}
}
控制台提示类型转换异常
利用FastJson,拼接复杂嵌套json数据&&直接从json字符串中(不依赖实体类)解析出键值对的更多相关文章
- JS解析json数据并将json字符串转化为数组的实现方法
json数据在ajax实现异步交互时起到了很重要的作用,他可以返回请求的数据,然后利用客户端的js进行解析,这一点体现出js的强大,本文介绍JS解析json数据并将json字符串转化为数组的实现方法, ...
- HttpServletResponse 返回的json数据不是json字符串,而是json对象
今天在改一个bug 情况: 在spring boot中写了一个类Result ,用来统一封装 各个API响应结果 , 其中重写了toString()方法来返回 json字符串 . 在正常情况下,从其它 ...
- 如何构建JSON数据,JSON数据的格式,JSON数据的获取
假设你是用$.getJSON();方法获取JSON数据$.getJSON(url,{"Action":"getStudent"},function(data){ ...
- Jquery Ajax和getJSON获取后台普通Json数据和层级Json数据解析
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- JS:字符串转成json数据,和json转成字符串方法 iframe获取父级传过来的数据
字符串转成json数据,和json转成字符串方法 //转为JSON adinfo=JSON.parse(adinfo) //转为字符串 adinfo=JSON.stringify(adinfo) 大概 ...
- c#实例化继承类,必须对被继承类的程序集做引用 .net core Redis分布式缓存客户端实现逻辑分析及示例demo 数据库笔记之索引和事务 centos 7下安装python 3.6笔记 你大波哥~ C#开源框架(转载) JSON C# Class Generator ---由json字符串生成C#实体类的工具
c#实例化继承类,必须对被继承类的程序集做引用 0x00 问题 类型“Model.NewModel”在未被引用的程序集中定义.必须添加对程序集“Model, Version=1.0.0.0, Cu ...
- js中解析json对象:JSON.parse()用于从一个字符串中解析出json对象, JSON.stringify()用于从一个对象解析出字符串。
JSON.parse()用于从一个字符串中解析出json对象. var str = '{"name":"huangxiaojian","age&quo ...
- EF Core中,通过实体类向SQL Server数据库表中插入数据后,实体对象是如何得到数据库表中的默认值的
我们使用EF Core的实体类向SQL Server数据库表中插入数据后,如果数据库表中有自增列或默认值列,那么EF Core的实体对象也会返回插入到数据库表中的默认值. 下面我们通过例子来展示,EF ...
- 网络传输中利用fastjson将复杂嵌套数据类型Json格式转换(GeoJsonPolygon)
如果一个对象太复杂了,那么在网络传输键的JSON格式数据转换容易出问题. 比如下面一个类Area.java import lombok.AllArgsConstructor; import lombo ...
随机推荐
- hostapd 热点设置
一. 需要安装的服务:hostapd dhcp(isc-dhcp-server) dns(dnsmasq或者bind9或者都不装设成8.8.8.8 ) 二.建hostapd.conf文件 ,su ...
- 汉诺塔(思维、DP思想)
链接:https://ac.nowcoder.com/acm/contest/3007/C来源:牛客网 题目描述 现在你有 N 块矩形木板,第 i 块木板的尺寸是 Xi*Yi,你想用这些木板来玩汉诺塔 ...
- [SUCTF 2019]EasyWeb
0x00 知识点 本题知识量巨大,把我给看傻了..盯着网上师傅们的博客看了好久.. 知识点1 构造不包含数字和字母的webshell 思路来自p牛 参考链接: https://www.leaveson ...
- HTTP协议(四):首部
前言 作者说:上一节中介绍了HTTP报文中的状态码,这一节同样是对报文的补充,介绍的是HTTP首部字段.不过,你如果是第一次见到这个东西,肯定会特别疑惑,什么是HTTP首部? <图解HTTP&g ...
- Django——CSRF防御
关于CSRF攻击原理在上一篇博客已经有过说明,这篇主要介绍下Django关于开启CSRF及CSRF工作机理.关于开启防御有两种,一种是全局开启,另一种是局部开启. 全局: 中间件 django.mid ...
- Q3:Longest Substring Without Repeating Characters
3. Longest Substring Without Repeating Characters 官方的链接:3. Longest Substring Without Repeating Chara ...
- Python Learning Day2
练习:login功能 def login(): with open(r'C:\Users\liubin\desktop\user.txt','r') as f: res=f.read() flag=1 ...
- 随机森林RF
bagging 随机森林顾名思义,是用随机的方式建立一个森林,森林里面有很多的决策树组成,随机森林的每一棵决策树之间是没有关联的.在得到森林之后,当有一个新的输 入样本进入的时候,就让森林中的每一棵决 ...
- ES6 之 第七种数据类型Symbol
概述 为了减少对象的属性名冲突,ES6引入新的原始数据类型Symbol,JS的第七种数据类型. Symbol 能够保证每个属性的名字都是独一无二,这样就能从根本上防止属性名冲突. Symbol 值能够 ...
- opencv摄像头捕获视频
1.ord()函数:它以一个字符(长度为1的字符串)作为参数,返回对应的 ASCII 数值,或者 Unicode 数值,如果所给的 Unicode 字符超出了你的 Python 定义范围,则会引发一个 ...