value);
2. 高级用法
2.1 实体类与json之间的转换
//实体类
@Data
@AllArgsConstructor
public class TestUser {
private String name;
private Integer age;
private Integer sex;
//测试类
//定义一个实体类对象用来演示
TestUser testUser = new TestUser("111",11,1);
//【实体类转json】
JSONObject jsonObj = (JSONObject)JSONObject.toJSON(testUser);
//结果:{"sex":1,"name":"111","age":11}
System.out.println(jsonObj);
//【json转实体类】 反序列化
TestUser testUserTemp = JSONObject.parseObject(jsonObj.toJSONString(), TestUser.class);
//结果:TestUser(name=111, age=11, sex=1)
System.out.println(testUserTemp);
//这里补充一个 list对象转json
//如果有值为null,会导致这个key都被默认去掉,需要加上SerializerFeature.WriteMapNullValue
List<User> list = new ArrayList<>();
JSONArray jsonArray = JSONArray.parseArray(JSON.toJSONString(list,SerializerFeature.WriteMapNullValue))
名称含义
QuoteFieldNames
输出key时是否使用双引号,默认为true
UseSingleQuotes
使用单引号而不是双引号,默认为false
WriteMapNullValue
是否输出值为null的字段,默认为false
WriteEnumUsingToString
Enum输出name()或者original,默认为false
UseISO8601DateFormat
Date使用ISO8601格式输出,默认为false
WriteNullListAsEmpty
List字段如果为null,输出为[],而非null
WriteNullStringAsEmpty
字符类型字段如果为null,输出为”“,而非null
WriteNullNumberAsZero
数值字段如果为null,输出为0,而非null
WriteNullBooleanAsFalse
Boolean字段如果为null,输出为false,而非null
SkipTransientField
如果是true,类中的Get方法对应的Field是transient,序列化时将会被忽略。默认为true
SortField
按字段名称排序后输出。默认为false
WriteTabAsSpecial
把\t做转义输出,默认为false 不推荐
PrettyFormat
结果是否格式化,默认为false
WriteClassName
序列化时写入类型信息,默认为false。反序列化是需用到
DisableCircularReferenceDetect
消除对同一对象循环引用的问题,默认为false
WriteSlashAsSpecial
对斜杠’/’进行转义
BrowserCompatible
将中文都会序列化为\uXXXX格式,字节数会多一些,但是能兼容IE6,默认为false
WriteDateUseDateFormat
全局修改日期格式,默认为false。JSON.DEFFAULT_DATE_FORMAT = “yyyy-MM-dd”;JSON.toJSONString(obj,SerializerFeature.WriteDateUseDateFormat);
DisableCheckSpecialChar
一个对象的字符串属性中如果有特殊字符如双引号,将会在转成json时带有反斜杠转移符。如果不需要转义,可以使用这个属性。默认为false
NotWriteRootClassName
BeanToArray
将对象转为array输出
WriteNonStringKeyAsString
NotWriteDefaultValue
BrowserSecure
IgnoreNonFieldGetter
WriteEnumUsingName
2.2 JSONField注解
那么如果我想要在实体类转json的时候,排除掉某些字段该怎么做呢?
使用@JSONField(serialize = false) 注解。
(是否参与序列化,false代表该字段不输出,但是如果加了final,这个字段就无法被过滤)
修改后的效果如下:
@Data
@AllArgsConstructor
public class TestUser {
@JSONField(serialize = false)
private String name;
private Integer age;
private Integer sex;
//定义一个实体类对象用来演示
TestUser testUser = new TestUser("111",11,1);
//【实体类转json】
JSONObject jsonObj = (JSONObject)JSONObject.toJSON(testUser);
//结果:{"sex":1,"age":11}
System.out.println(jsonObj);
//【json转实体类】 反序列化
TestUser testUserTemp = JSONObject.parseObject(jsonObj.toJSONString(), TestUser.class);
//结果:TestUser(name=null, age=11, sex=1)
System.out.println(testUserTemp);
那么如果我想要在实体类转json的时候,不使用实体类中的名称该如何做呢?
使用@JSONField(name = "别名") 注解。
使用字段别名,效果如下:
@Data
@AllArgsConstructor
public class TestUser {
@JSONField(name = "t_name")
private String name;
private Integer age;
private Integer sex;
//定义一个实体类对象用来演示
TestUser testUser = new TestUser("111",11,1);
//【实体类转json】
JSONObject jsonObj = (JSONObject)JSONObject.toJSON(testUser);
//结果:{"t_name":"111","sex":1,"age":11}
System.out.println(jsonObj);
//【json转实体类】 反序列化
TestUser testUserTemp = JSONObject.parseObject(jsonObj.toJSONString(), TestUser.class);
//结果:TestUser(name=111, age=11, sex=1)
System.out.println(testUserTemp);
那么如果现在有个时间类型的字段,我想要以固定的格式输出,该怎么办呢?
使用@JSONField(format="yyyy-MM-dd HH:mm:ss") 注解。
下面先添加一个时间字段date,看看添加前后的效果:
@Data
@AllArgsConstructor
public class TestUser {
private String name;
private Integer age;
private Integer sex;
@JSONField(format="yyyy-MM-dd HH:mm:ss")
private Date date;
//定义一个实体类对象用来演示
TestUser testUser = new TestUser("111",11,1,new Date());
//【实体类转json】
JSONObject jsonObj = (JSONObject)JSONObject.toJSON(testUser);
//添加前结果:{"date":1600485884579,"sex":1,"name":"111","age":11}
//添加后结果:{"date":"2020-09-19 11:25:46","sex":1,"name":"111","age":11}
System.out.println(jsonObj);
//【json转实体类】 反序列化
TestUser testUserTemp = JSONObject.parseObject(jsonObj.toJSONString(), TestUser.class);
//添加前结果:TestUser(name=111, age=11, sex=1, date=Sat Sep 19 11:24:44 CST 2020)
//添加后结果:TestUser(name=111, age=11, sex=1, date=Sat Sep 19 11:25:46 CST 2020)
System.out.println(testUserTemp);
那么如果某个字段的值是null,在序列化的时候,可以看到生成的字符串中没有对应的key,那么我想要实现,如果值为空,给其一个默认值:
这里要提及一个知识:SerializerFeature属性,下面列举几个,详细的可以去查api
参考:https://www.cnblogs.com/wbxk/p/10064737.html
字符类型字段如果为null,输出为"",而非null WriteNullStringAsEmpty
数值字段如果为null,输出为0,而非null WriteNullNumberAsZero
Boolean字段如果为null,输出为false,而非null WriteNullBooleanAsFalse
List字段如果为null,输出为[],而非null WriteNullListAsEmpty
@Data
@AllArgsConstructor
public class TestUser {
@JSONField(serialzeFeatures=SerializerFeature.WriteNullStringAsEmpty)
private String name;
private Integer age;
private Integer sex;
@JSONField(format="yyyy-MM-dd HH:mm:ss")
private Date date;
//定义一个实体类对象用来演示
TestUser testUser = new TestUser(null,11,1,new Date());
String jsonStr = JSON.toJSONString(testUser);
//加注解前:{"age":11,"date":"2020-09-19 12:49:07","sex":1}
//加注解后:{"age":11,"date":"2020-09-19 12:48:28","name":"","sex":1}
System.out.println(jsonStr);
现在想要将json对象转换成实体类对象,方法如下:
@Data
public class TestUser {
private String name;
private Integer age;
private Integer sex;
private Date date;
//定义一个实体类对象用来演示
TestUser testUser = new TestUser();
testUser.setName("11");
testUser.setAge(11);
testUser.setSex(1);
String jsonStr = JSON.toJSONString(testUser);
//实体类转成json对象
JSONObject jsonObject = JSONObject.parseObject(jsonStr);
//【json对象转成实体类】
TestUser testUserTemp = JSON.toJavaObject(jsonObject, TestUser.class);
//结果:TestUser(name=11, age=11, sex=1, date=null)
System.out.println(testUserTemp);
这里要注意:上面的例子里我都是用的@AllArgsConstructor来方便我创建实体类数据,但是我发现如果加上了这个注解,在使用toJavaObject方法的时候会报错。不使用这个注解没有问题。报错信息如下:
网上搜的结果为:
实体类中存在内嵌的其它类,将内部类修改为静态内部类即可,但是我这里也没有发现有内部类的字段,于是我尝试将Date类型的屏蔽,结果成功了,暂时还没有想清楚是什么问题
//报错代码如下
@Data
@AllArgsConstructor
public class TestUser {
private String name;
private Integer age;
private Integer sex;
private Date date;
//定义一个实体类对象用来演示
TestUser testUser = new TestUser("111",11,1,new Date());
String jsonStr = JSON.toJSONString(testUser);
JSONObject jsonObject = JSONObject.parseObject(jsonStr);
TestUser testUserTemp = JSON.toJavaObject(jsonObject, TestUser.class);
二、 JsonArray
JsonArray:即json数组,由多个json对象(jsonObject)组成
//定义一个json数组类型的字符串用来演示
String jsonstr = "[{\"sex\":\"1\",\"name\":\"111\",\"age\":\"11\"},{\"sex\":\"0\", \"name\":\"222\",\"age\":\"21\"}]";
//【String转jsonArray】
JSONArray jsonArray = JSONArray.parseArray(jsonstr);
//【jsonArray转String】
String jsonstrTemp = JSON.toJSONString(jsonArray);
//【jsonArray转list】
List list = JSONObject.parseArray(jsonArray.toJSONString());
//【jsonArray转list-->对象】
List<TestUser> testUsers = JSONObject.parseArray(jsonArray.toJSONString(), TestUser.class);
//【list转jsonArray】
List listTemp = new ArrayList();
JSONArray array = JSONArray.parseArray(JSON.toJSONString(listTemp));
//【list转jsonArray--->对象】
List<TestUser> testUserList = new ArrayList<>();
JSONArray array1 = JSONArray.parseArray(JSON.toJSONString(listTemp));
//【String转List】
List<TestUser> testUserList1 = JSONObject.parseArray(jsonstr, TestUser.class);
//【循环获取jsonArray中所有的jsonObject】
for (int i = 0; i < jsonArray.size(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
String id = jsonObject.getString("sex");
String name = jsonObject.getString("name");
//这里要注意:age字段也可以用getString方法来获取
Integer age = jsonObject.getInteger("age");
三、JsonObject+JsonArray
如何判断一个不确定格式的json串,每个key对应的类型呢?
//【判断json类型】
String text0 = "11";
String text2 = "{ \"sex\":\"1\", \"name\":\"张三\", \"age\":\"11\"}";
String text3 = "[{ \"sex\":\"1\", \"name\":\"张三\", \"age\":\"11\"},{ \"sex\":\"0\", \"name\":\"李四\", \"age\":\"21\"}]";
Object parse0 = JSON.parse(text0);
System.out.println(parse0 instanceof java.lang.Integer);//true
Object parse2 = JSON.parse(text2);
System.out.println(parse2 instanceof JSONObject);//true
Object parse3 = JSON.parse(text3);
System.out.println(parse3 instanceof JSONArray);//true