- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章深入剖析构建JSON字符串的三种方式(推荐)由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
前言:JSON 是轻量级的数据交换格式,很常用,尤其是在使用 Ajax 时,在后台将数据封装为 JSON 字符串更是常见。之前在做项目的时候用过几种方式在后端将数组或 List 集合转换为 JSON 字符串,现在回想起来竟然又有些遗忘。现在来一个汇总,把这几种构建 JSON 字符串的方式彻底回忆起来.
笔记中提供了大量的代码示例,需要说明的是,大部分代码示例都是本人所敲代码并进行测试,不足之处,请大家指正~ 。
1、alibaba 的 Fastjson 。
1.Fastjson 是一个以 Java 语言编写的 JSON 处理器,由阿里巴巴公司开发,功能强大.
要使用第三方的工具当然要导入 jar 包了,只需导入 fastjson-1.2.8.jar 即可,jar 包的获取,大家可以直接去网上下载 ,也可以联系本人.
先来一个 fastjson 的简单实例吧,如下代码构造了一个 Customer 的实例,并将此实例转化成为 JSON 字符串,调用了 com.alibaba.fastjson.JSON 的 toJSONString() 方法,将 Customer 实例传入 。
1
2
3
4
5
6
7
8
9
10
11
|
@Test
public void test1() {
Customer customer = new Customer();
customer.setId(1);
customer.setCustName("Tom");
customer.setAddress("BeiJing");
String jsonStr = JSON.toJSONString(customer);
System.out.println(jsonStr);
}
|
打印结果:{"address":"BeiJing","custName":"Tom","id":1} 。
再来一个小测试,将一个 List 的 Customer 的集合转换为 JSON 字符串,22 行还是直接调用 JSON 的 toJSONString() 方法,将 List 集合传入即可 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
/**
* 将 List 集合转换为 JSON 字符串
*/
@Test
public void test2() {
List<
Customer
> lists = new ArrayList<>();
Customer customer = new Customer();
customer.setId(1);
customer.setCustName("Tom");
customer.setAddress("BeiJing");
lists.add(customer);
Customer customer2 = new Customer();
customer2.setId(1);
customer2.setCustName("Bob");
customer2.setAddress("ShangHai");
lists.add(customer2);
String jsonStr = JSON.toJSONString(lists);
System.out.println(jsonStr);
}
|
打印结果:[{"address":"BeiJing","custName":"Tom","id":1},{"address":"ShangHai","custName":"Bob","id":1}] 。
2. 深入研究一下,我们看下面这种情况:3 行创建了一个 List 的 Customer 集合,10 和 11 行进行了一个重复的 add 操作,那么打印结果是什么样的呢?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
@Test
public void test3() {
List<
Customer
> lists = new ArrayList<>();
Customer customer = new Customer();
customer.setId(1);
customer.setCustName("Tom");
customer.setAddress("BeiJing");
lists.add(customer);
lists.add(customer);
String jsonStr = JSON.toJSONString(lists);
System.out.println(jsonStr);
}
|
打印结果:[{"address":"BeiJing","custName":"Tom","id":1},{"$ref":"$[0]"}],大家看,第二个 Customer 实例没有打印出,这就证明了 fastjson 默认禁止循环的引用,如果想改变这种情况,需要在 JSON 的 toJSONString() 方法中传递第二个参数 SerializerFeature.DisableCircularReferenceDetect 即可解决,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
@Test
public void test3() {
List<
Customer
> lists = new ArrayList<>();
Customer customer = new Customer();
customer.setId(1);
customer.setCustName("Tom");
customer.setAddress("BeiJing");
lists.add(customer);
lists.add(customer);
String jsonStr = JSON.toJSONString(lists, SerializerFeature.DisableCircularReferenceDetect);
System.out.println(jsonStr);
}
|
此时的打印结果为:[{"address":"BeiJing","custName":"Tom","id":1},{"address":"BeiJing","custName":"Tom","id":1}],建议以后再使用 JSON 的 toJSONString() 方法时将第二个参数添加上 。
3.再深入一点,来看一个常见的问题,Department 和 Manager 类维护双向一对一的关联关系,Department 类中有 Manager 类的引用,Manager 类中有 Department 类的引用,来看如下代码:在 11 和 12 行设置了关联关系,14 行和 15 行进行 JSON 字符串的转换,结果会怎样呢?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
@Test
public void test4() {
Manager mgr = new Manager();
mgr.setMgrId(1);
mgr.setMgrName("Tom");
Department dept = new Department();
dept.setDeptId(2);
dept.setDeptName("DEV");
mgr.setDept(dept);
dept.setManager(mgr);
String jsonStr = JSON.toJSONString(dept, SerializerFeature.DisableCircularReferenceDetect);
// String jsonStr = JSON.toJSONString(mgr, SerializerFeature.DisableCircularReferenceDetect);
System.out.println(jsonStr);
}
|
答案是,抛出了异常,常见的 java.lang.StackOverflowError,抛异常的原因是双方都维护关联关系进入了死循环,那么如何解决这个问题呢?可以在一方添加 @JSONField(serialize=false) 注解,7 行所示,即可解决 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
public class Department {
private Integer deptId;
private String deptName;
@JSONField(serialize=false)
private Manager manager;
public Integer getDeptId() {
return deptId;
}
public void setDeptId(Integer deptId) {
this.deptId = deptId;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public Manager getManager() {
return manager;
}
public void setManager(Manager manager) {
this.manager = manager;
}
}
|
打印结果为:{"dept":{"deptId":2,"deptName":"DEV"},"mgrId":1,"mgrName":"Tom"},结果也很令人满意.
4.最后提供一个 fastjson 的工具类,开发时可以直接使用,供大家参考 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
package qi.ssh.utils;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
public class FastJsonUtil {
/**
* 将对象转成json串
* @param object
* @return
*/
public static String toJSONString(Object object){
//DisableCircularReferenceDetect来禁止循环引用检测
return JSON.toJSONString(object,SerializerFeature.DisableCircularReferenceDetect);
}
//输出json
public static void write_json(HttpServletResponse response,String jsonString)
{
response.setContentType("application/json;utf-8");
response.setCharacterEncoding("UTF-8");
try {
response.getWriter().print(jsonString);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* ajax提交后回调的json字符串
* @return
*/
public static String ajaxResult(boolean success,String message)
{
Map map=new HashMap();
map.put("success", success);//是否成功
map.put("message", message);//文本消息
String json= JSON.toJSONString(map);
return json;
}
/**
* JSON串自动加前缀
* @param json 原json字符串
* @param prefix 前缀
* @return 加前缀后的字符串
*/
public static String JsonFormatterAddPrefix(String json,String prefix,Map<
String
,Object> newmap)
{
if(newmap == null){
newmap = new HashMap();
}
Map<
String
,Object> map = (Map) JSON.parse(json);
for(String key:map.keySet())
{
Object object=map.get(key);
if(isEntity(object)){
String jsonString = JSON.toJSONString(object);
JsonFormatterAddPrefix(jsonString,prefix+key+".",newmap);
}else{
newmap.put(prefix+key, object);
}
}
return JSON.toJSONString(newmap);
}
/**
* 判断某对象是不是实体
* @param object
* @return
*/
private static boolean isEntity(Object object)
{
if(object instanceof String )
{
return false;
}
if(object instanceof Integer )
{
return false;
}
if(object instanceof Long )
{
return false;
}
if(object instanceof java.math.BigDecimal )
{
return false;
}
if(object instanceof Date )
{
return false;
}
if(object instanceof java.util.Collection )
{
return false;
}
return true;
}
}
|
2、Jackson 。
1.同样也需要导入 jar 包,Jackson 导入的 jar 包有三个 。
具体使用也通过一个小例子说明:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
package com.software.jackson;
import java.util.Arrays;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Customer {
private int id;
private String name;
public Customer(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCity(){
return "BeiJing";
}
@JsonIgnore
public String getSchool(){
return "School";
}
public static void main(String[] args) throws JsonProcessingException {
//创建ObjectMapper对象
ObjectMapper mapper = new ObjectMapper();
Customer customer = new Customer(1, "Tom");
List<
Customer
> lists = Arrays.asList(customer, new Customer(2, "Bob"));
//调用 ObjectMapper 的 writeValueAsString(xxx) 方法,把一个对象或几个传入,转为一个 JSON 字符串
String jsonStr = mapper.writeValueAsString(lists);
System.out.println(jsonStr);
}
}
|
定义了一个 Customer 类,38 行和 43 行定义了两个额外的 get 方法并直接赋值,main 方法中创建 ObjectMapper 的对象,调用其 writeValueAsString() 方法,传入单个对象或对象的集合,便会返回对应的 JSON 字符串,打印结果为:[{"id":1,"name":"Tom","city":"BeiJing"},{"id":2,"name":"Bob","city":"BeiJing"}],大家可能会发现,我们 43 行定义的 getSchool() 方法中的 School 没有被打印出,这是因为我们在此方法上添加了 @JsonIgnore 注解,添加了此注解,在构造 JSON 字符串时便忽略此属性,细想一下 ,此注解添加到 get 方法上,这也说明 Jackson 构造 JSON 字符串时基于 getter 方法的.
2.与之前一样,我们想看一看 Jackson 有没有禁止循环的引用,类似的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
@Test
public void test2() throws JsonProcessingException {
List<
Customer
> lists = new ArrayList<>();
Customer customer = new Customer();
customer.setId(1);
customer.setCustName("Tom");
customer.setAddress("BeiJing");
lists.add(customer);
lists.add(customer);
ObjectMapper mapper = new ObjectMapper();
String jsonStr = mapper.writeValueAsString(lists);
System.out.println(jsonStr);
}
|
来看一下输出结果:[{"id":1,"custName":"Tom","address":"BeiJing"},{"id":1,"custName":"Tom","address":"BeiJing"}],结果显而易见.
3.我们再来看一看如果像 Fastjson 中测试的 Department 和 Manager 双向一对一映射的例子,Jackson 会表现的怎么样:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
@Test
public void test1() throws JsonProcessingException {
Manager mgr = new Manager();
mgr.setMgrId(1);
mgr.setMgrName("Tom");
Department dept = new Department();
dept.setDeptId(2);
dept.setDeptName("DEV");
mgr.setDept(dept);
dept.setManager(mgr);
ObjectMapper mapper = new ObjectMapper();
String jsonStr = mapper.writeValueAsString(dept);
System.out.println(jsonStr);
}
|
直接运行还是会出相同的异常 Caused by: java.lang.StackOverflowError,我们的思路与测试 Fastjson 一样,为 Department 中的 Manager 引用添加 @JsonIgnore 注解,异常解决了,但打印结果是很满意,结果为:{"deptId":2,"deptName":"DEV"} ,远不如 Fastjson 的输出结果。由此可以看出 Fastjson 功能之强大.
3、Google Gson 。
1.看看如何使用:jar 包呢只需要一个 gson-2.2.4.jar ,普通对象与集合转为 JSON 没有什么可说的,简单演示一下将 List 集合转为 JSON 字符串吧,直接 new 出 Gson 的对象,调用其 toJson() 方法传入需要转换的对象即可.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
@Test
public void test2() {
List<
Customer
> lists = new ArrayList<>();
Customer customer = new Customer();
customer.setId(1);
customer.setCustName("Tom");
customer.setAddress("BeiJing");
lists.add(customer);
Customer customer2 = new Customer();
customer2.setId(1);
customer2.setCustName("Bob");
customer2.setAddress("ShangHai");
lists.add(customer2);
Gson gson = new Gson();
String jsonStr = gson.toJson(lists);
System.out.println(jsonStr);
}
|
打印结果:[{"address":"BeiJing","custName":"Tom","id":1},{"address":"ShangHai","custName":"Bob","id":1}] 。
2. 那有没有禁止循环引用呢?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
@Test
public void test3() {
List<
Customer
> lists = new ArrayList<>();
Customer customer = new Customer();
customer.setId(1);
customer.setCustName("Tom");
customer.setAddress("BeiJing");
lists.add(customer);
lists.add(customer);
Gson gson = new Gson();
String jsonStr = gson.toJson(lists);
System.out.println(jsonStr);
}
|
输出结果:[{"id":1,"custName":"Tom","address":"BeiJing"},{"id":1,"custName":"Tom","address":"BeiJing"}],显而易见是没有的.
3.若有双向一对一的关联关系映射的话,Google Gson 也是会有死循环问题造成 java.lang.StackOverflowError 异常,但是 Gson 并没有为我们提供一个注解,要解决此问题LZ提供一个解决方案的思路,Google Gson 使用的是 ExclusionStrategy 策略进行某个字段或某个域的序列化,可以通过此接口自定义一个 注解来解决此问题。但是建议大家如果涉及到双向关联关系的对象转换为 JSON 的需求是,使用 Fastjson.
4、三种方式的简单比较 。
LZ 从以下几个方面来比较构造 JSON 字符串的三种方式:
1. jar 包方面:显然是 Fastjson 和 Google Gson 胜出,Jackson 需要加入 3 个 jar 包.
2. 简单对象或集合转为 JSON:若是普通的简单对象或集合进行转换,可能 Jackson 和 Google Gson 要胜出一些了,起码构造比较方便.
3. 涉及到双向关联关系的转换:毫无疑问阿里巴巴的 Fastjson 将胜出.
建议大家在实际的开发中根据自己的需求合理选择某一方式.
以上这篇深入剖析构建JSON字符串的三种方式(推荐)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我.
原文链接:http://www.cnblogs.com/crawl/p/7701856.html 。
最后此篇关于深入剖析构建JSON字符串的三种方式(推荐)的文章就讲到这里了,如果你想了解更多关于深入剖析构建JSON字符串的三种方式(推荐)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我在使用 gradle 构建一个特定应用程序时遇到问题。该应用程序可以用 eclipse 编译和构建,它在平板电脑上运行良好。当我尝试使用 Gradle 构建它时,“compileDebugJava”
我有一个 C 程序,是一位离开的开发人员留给我的。我试图弄清楚他到底在做什么,并将软件重新安排成更合乎逻辑的东西,这样我就可以更轻松地构建它。我正在使用 CMake 构建,而他使用的是 Make。 有
我刚开始阅读“Pro Spring MVC with web flow”,它附带了一个我想遵循的代码示例。 我要什么 - 我想像书中那样构建应用程序,使用 Gradle 有什么问题 - 我没用过 Gr
我希望有人已经这样做了。我正在尝试为我的一个 angular 2 项目在 teamcity 中建立一个连续的构建。在做了一些研究之后,我按照以下步骤操作: 构建步骤 1:为 teamcity 安装 j
我有一个旧的 ASP.Net 网站解决方案,看起来像: 当我在 Visual Studio 中构建解决方案时,我得到以下输出: ------ Build started: Project: C:\..
我使用 gulp-usref、gulp-if、gulp-uglify、gulp-csso 和 gulp-file-include 来构建我的应用程序。除了 HTML 保持原样外,构建中的一切都运行良好
我正在使用 ionic2 开发内部移动应用程序。我可以通过以下方式成功构建 ios: ionic build ios and ionic build ios --prod 但当我这样做时,它一直失败
我是一位经验丰富的 .NET/C# 开发人员,但对这里的几乎所有技术/库(包括 SQL/DB 工作)都是新手。 我正在开发一个具有 Azure/Entity Framework .NET 后端和可移植
我正在使用 VS 2008。我可以使用 IDE 成功编译我的解决方案。但是,当我尝试使用 devenv.com 构建它时,它失败并提示“错误:找不到项目输出组'(无法确定名称)的输出”。该组、其配置或
版本: ember.js 2.7,ember-data 2.7 ember-cli 2.9.1//同样适用于 ember-cli 2.7 node 6.9.1, npm 3.10.9//也适用于 no
我第一次修补 AzureDevops,设置一些 CI 任务。 我有一个公共(public)存储库(开源)和一个包含 3 个 F# 项目的解决方案(.sln)。该解决方案在 Windows/Mac/Li
目前 5.1.5 版本或 STLPort CVS 存储库似乎仍不支持 VS2008。如果有人已经完成了这项工作,那么如果可能的话,分享会很有用:) 同样,了解 VS2005 或 2008 x64 构建
我有一个 Python 2.7 项目,到目前为止一直使用 gfortran 和 MinGW 来构建扩展。我使用 MinGW,因为它似乎支持 Fortran 代码中的写入语句和可分配数组,而 MSVC
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题? Update the question所以它是on-topic对于堆栈溢出。 9年前关闭。 Improve this que
我想知道为什么在 Zimbra Wiki 中只列出了构建过程的特定平台。这意味着不可能在其他 Linux 发行版上构建 Zimbra? Zimbra 社区选择一个特殊的 Linux 发行版来构建 Zi
我将在 Swift 中构建一个 CLI 工具。我用这个命令创建了项目 swift package init --type executable当我构建我的项目并解析 时读取别名 Xcode 中的参数并
我想为添加到 docker 镜像的文件设置文件权限。我有这个简单的 Dockerfile: FROM ubuntu:utopic WORKDIR /app RUN groupadd -g 1000 b
当我使用 clBuildProgram在我的 OpenCl 代码中,它失败并显示错误代码 -11,没有任何日志信息。 这是我的代码的样子: ret = clBuildProgram(program
我有一个底部导航栏,它有一个列表页面,该页面使用状态块。 class _MainPageState extends State { int _index = 0; @override Wi
我在本地计算机上使用Jenkins(Jenkins URL未通过Internet公开,但该计算机上已启用Internet。) 我进行了以下配置更改: 在Jenkins工具上安装了Git和Github插
我是一名优秀的程序员,十分优秀!