在Java中操作Json对象时,经常遇到以下几种情况:
Json字符串与Json对象的转换
Json对象与Java对象的转换
以下使用json-lib第3方工具进行讲解
其中Java对象→Json对象→Json字符串用的较多,其操作也较为简单,
1.Java对象→Json对象
private static void JavaObj2JsonObj() {//将Java对象转换成Json对象,转换后的类型为JSONObjectJSONObject jsonObj = JSONObject.fromObject(javaObj);//对象Map对象,也使用JSONObject的putAll方法将map内的键值对转换为Json对象中的属性-值HashMap map = new HashMap();map.put("tel", "13566662222");jsonObj.putAll(map);//put方法可设置一个属性值jsonObj.put("key","123");//element方法返回Json对象本身,可以进行串联调用jsonObj.element("name", "java").element("length", 4);List
输出结果如下:
{"born":{"time":1572407278199,"minutes":47,"seconds":58,"hours":11,"month":9,"year":119,"timezoneOffset":-480,"day":3,"date":30},"tel":"13566662222","name":"java","age":11,"length":4,"key":"123"}[{"born":{"time":1572407278199,"minutes":47,"seconds":58,"hours":11,"month":9,"timezoneOffset":-480,"year":119,"day":3,"date":30},"age":11,"name":"john"},{"born":{"time":1572407278199,"minutes":47,"seconds":58,"hours":11,"month":9,"timezoneOffset":-480,"year":119,"day":3,"date":30},"age":11,"name":"john"}]
1.1日期对象的处理
可以看到,在Java对象到Json对象转换时,相对较为简单,但对日期这类较特殊的对象进行转换时,默认会转换成一个对象,在转换为Json对象时会按一般对象进行处理,转换后的内容可读性较差,如何将日期对象转换为可读性强的日期字符串呢?这就要用到类了,使用类可以指定转换规则,如果想将日期对象转换为yyyy-MM-dd HH:mm:ss.SSS的字符串,就可以使用以下的代码:
private static void JavaObj2JsonObjFmtDate() {JsonConfig cfg = new JsonConfig();cfg.registerJsonValueProcessor(Date.class, new JsonValueProcessor() {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");public Object processObjectValue(String propt, Object val, JsonConfig cfg) {return processArrayValue(val, cfg);}public Object processArrayValue(Object val, JsonConfig arg1) {if(val instanceof Date){return sdf.format((Date)val);}return null;}});JSONObject json = JSONObject.fromObject(javaObj);System.out.println("default json string:");System.out.println(json.toString());System.out.println("with JsonConfig which register Date processor:");json = JSONObject.fromObject(javaObj, cfg);System.out.println(json.toString());}
使用这段代码后,日期对象将转换为字符串格式,可读性大大提高,输出结果如下所示:
default json string:{"born":{"time":1572406936364,"minutes":42,"seconds":16,"hours":11,"month":9,"year":119,"timezoneOffset":-480,"day":3,"date":30},"name":"john","age":11}with JsonConfig which register Date processor:{"born":"2019-10-30 11:42:16.364","name":"john","age":11}
1.2Java对象属性过滤
如果想在转换时,指定某些属性不转换到Json对象时该怎么办呢?看代码:
private static void JavaObj2JsonObjFilterPropt() {JsonConfig cfg = new JsonConfig();cfg.setJsonPropertyFilter(new PropertyFilter() {public boolean apply(Object obj, String propt, Object val) {if("born".equals(propt)){return true;//返回true时表示此字段不转换至Json对象中}return false;}});JSONObject json = JSONObject.fromObject(javaObj);System.out.println("default json string:");System.out.println(json.toString());System.out.println("with JsonConfig which filter born propt:");json = JSONObject.fromObject(javaObj, cfg);System.out.println(json.toString());}
接口中仅有一个apply方法,此方法有3个参数,可以根据需要对指定的字段进行过滤,当返回true时表示要过滤此字段
输出结果如下:
default json string:{"born":{"time":1572407140061,"minutes":45,"seconds":40,"hours":11,"month":9,"year":119,"timezoneOffset":-480,"day":3,"date":30},"name":"john","age":11}with JsonConfig which filter born propt:{"name":"john","age":11}
2.Json对象到Json字符串
Json对象到Json字符串最简单,默认使用方法即可返回字符串,如果要使用缩进模式输出,则在中增加缩进数量的参数,直接看代码吧:
private static void JsonObj2JsonStr() {JSONObject json = JSONObject.fromObject(javaObj);System.out.println(json.toString());//每层缩进2个空白字符System.out.println(json.toString(2));//每层缩进2个空白字符,顶层缩进1个空白字符System.out.println(json.toString(2, 1));}
输出结果如下:
{"born":{"time":1572413765947,"minutes":36,"seconds":5,"hours":13,"month":9,"year":119,"timezoneOffset":-480,"day":3,"date":30},"name":"john","age":11}{"born":{"time": 1572413765947,"minutes": 36,"seconds": 5,"hours": 13,"month": 9,"year": 119,"timezoneOffset": -480,"day": 3,"date": 30},"name": "john","age": 11}{"born":{"time": 1572413765947,"minutes": 36,"seconds": 5,"hours": 13,"month": 9,"year": 119,"timezoneOffset": -480,"day": 3,"date": 30},"name": "john","age": 11}
压缩存储空间时不要使用缩进,做为展示内容时可设置缩进长度为2,此时显示效果最好,顶层缩进在一般情况下用处不大 。
3.Json字符串到Json对象
Json字符串到Json对象比较简单,只需要调用和对象的静态方法 ,传入Json字符串,即可得到Json对象
private static void JsonStr2JsonObj() {JSONObject json = JSONObject.fromObject(javaObj);String jsonStr = json.toString();json = JSONObject.fromObject(jsonStr);System.out.println(json.toString());JSONArray jsonAry = new JSONArray();jsonAry.add(javaObj);jsonStr = jsonAry.toString();jsonAry = JSONArray.fromObject(jsonStr);System.out.println(jsonAry.toString());}
输出结果如下:
{"born":{"time":1572414590736,"minutes":49,"seconds":50,"hours":13,"month":9,"year":119,"timezoneOffset":-480,"day":3,"date":30},"age":11,"name":"john"}[{"born":{"time":1572414590736,"minutes":49,"seconds":50,"hours":13,"month":9,"timezoneOffset":-480,"year":119,"day":3,"date":30},"name":"john","age":11}]
3.1Json对象属性过滤
转换时如果不需要某些属性,可以使用对象进行过滤
private static void JsonStr2JsonObjFilterPropt() {JsonConfig cfg = new JsonConfig();cfg.setJsonPropertyFilter(new PropertyFilter() {public boolean apply(Object obj, String propt, Object val) {if("born".equals(propt)){return true;//返回true时表示此字段不转换至Json对象中}return false;}});JSONObject json = JSONObject.fromObject(javaObj);String jsonStr = json.toString();System.out.println(jsonStr);json = JSONObject.fromObject(jsonStr, cfg);System.out.println(json.toString());}
输出结果如下:
{"born":{"time":1572414590736,"minutes":49,"seconds":50,"hours":13,"month":9,"year":119,"timezoneOffset":-480,"day":3,"date":30},"name":"john","age":11}{"age":11,"name":"john"}
4.Json对象到Java对象
对象的静态方法可以将一个Json对象转换为Java对象
private static void JsonObj2JavaObj() {JSONObject json = JSONObject.fromObject(javaObj);Object obj = JSONObject.toBean(json);System.out.println(obj);}
调用后输出结果如下:
net.sf.ezmorph.bean.MorphDynaBean@340d1fa5[{born=net.sf.ezmorph.bean.MorphDynaBean@4998a455[{time=1572416609829, minutes=23, seconds=29, hours=14, month=9, year=119, timezoneOffset=-480, day=3, date=30}], name=john, age=11}]
4.1指定转换的Java类
发现通过类的对象转换成Json对象后,再用方法转换为Java对象时,变成了,如何将转换后的对象仍变成呢?还是要使用对象
private static void JsonObj2JavaObjSetRootClass() {JSONObject json = JSONObject.fromObject(javaObj);System.out.println(json.toString());JsonConfig cfg = new JsonConfig();cfg.setRootClass(JsonNode.class);Object obj = JSONObject.toBean(json, cfg);System.out.println(obj);}
此时输出结果如下:
{"born":{"time":1572417309515,"minutes":35,"seconds":9,"hours":14,"month":9,"year":119,"timezoneOffset":-480,"day":3,"date":30},"name":"john","age":11}14:35:09 WARN [net.sf.json.JSONObject] - Property 'timezoneOffset' has no write method. SKIPPED.14:35:09 WARN [net.sf.json.JSONObject] - Property 'day' has no write method. SKIPPED.net.sf.json.JsonNode@54bb7759
4.2转换时过滤属性
此时输出的类是正确的,但出现了WARN的警告,提示和day属性没有写方法,如何消除这些警告呢?可以在中增加属性过滤
private static void JsonObj2JavaObjFilterPropt() {JSONObject json = JSONObject.fromObject(javaObj);System.out.println(json.toString());JsonConfig cfg = new JsonConfig();cfg.setRootClass(JsonNode.class);cfg.setJavaPropertyFilter(new PropertyFilter() {public boolean apply(Object obj, String propt, Object val) {if("timezoneOffset".equals(propt) || "day".equals(propt)){return true;//返回true时表示此字段不转换至Json对象中}return false;}});Object obj = JSONObject.toBean(json, cfg);System.out.println(obj);}
输出结果如下:
{"born":{"time":1572417839524,"minutes":43,"seconds":59,"hours":14,"month":9,"year":119,"timezoneOffset":-480,"day":3,"date":30},"name":"john","age":11}net.sf.json.JsonNode@1d10c424
4.3日期字符串转换为日期对象
如果Json对象中的日期是格式化日期字符串,此时在转换为Java对象时要进行特殊的处理,要注册日期转换对象,此行代码只需在方法执行前执行即可,放在静态代码块执行也可以 。
private static void JsonObj2JavaObjFmtDate() {JsonConfig cfg = new JsonConfig();cfg.registerJsonValueProcessor(Date.class, new JsonValueProcessor() {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");public Object processObjectValue(String propt, Object val, JsonConfig cfg) {return processArrayValue(val, cfg);}public Object processArrayValue(Object val, JsonConfig arg1) {if(val instanceof Date){return sdf.format((Date)val);}return null;}});JSONObject json = JSONObject.fromObject(javaObj, cfg);System.out.println(json.toString());//此行非常重要,如果没有此行代码,则日期字符串不能被正确转换为Java的日期对象,可能为空或指定为当前时间JSONUtils.getMorpherRegistry().registerMorpher(new DateMorpher(new String[] {"yyyy-MM-dd", "yyyy-MM-dd HH:mm", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm:ss.SSS"}));cfg = new JsonConfig();cfg.setRootClass(JsonNode.class);Object obj = JSONObject.toBean(json, cfg);System.out.println(obj);}
输出结果如下:
{"born":"2019-10-30 14:50:23.312","name":"john","age":11}net.sf.json.JsonNode@32b0bad7
4.4指定转换时各属性对应的类
如果要转换的Java类有多层嵌套,如何指定类模板呢?
private static void JsonObj2JavaObjSetProptClass() {JsonMainNode jmn = new JsonMainNode();jmn.setName("mainNode");jmn.setJsonNode(javaObj);jmn.setChildren(new ArrayList
输出结果如下:
{"name":"mainNode","jsonNode":{"born":{"time":1572419153235,"minutes":5,"seconds":53,"hours":15,"month":9,"year":119,"timezoneOffset":-480,"day":3,"date":30},"name":"john","age":11},"children":[{"born":{"time":1572419153235,"minutes":5,"seconds":53,"hours":15,"month":9,"timezoneOffset":-480,"year":119,"day":3,"date":30},"age":11,"name":"john"}]}15:05:53 WARN [net.sf.json.JSONObject] - Property 'timezoneOffset' has no write method. SKIPPED.15:05:53 WARN [net.sf.json.JSONObject] - Property 'day' has no write method. SKIPPED.net.sf.json.JsonMainNode@3f57fb52net.sf.json.JsonNode@2934e4fb[net.sf.ezmorph.bean.MorphDynaBean@4fa52fdf[{born=net.sf.ezmorph.bean.MorphDynaBean@65ea0252[{time=1572419153235, minutes=5, seconds=53, hours=15, month=9, timezoneOffset=-480, year=119, day=3, date=30}], age=11, name=john}]]15:05:53 WARN [net.sf.json.JSONObject] - Property 'timezoneOffset' has no write method. SKIPPED.15:05:53 WARN [net.sf.json.JSONObject] - Property 'day' has no write method. SKIPPED.15:05:53 WARN [net.sf.json.JSONObject] - Property 'timezoneOffset' has no write method. SKIPPED.15:05:53 WARN [net.sf.json.JSONObject] - Property 'day' has no write method. SKIPPED.net.sf.json.JsonMainNode@528acf6enet.sf.json.JsonNode@17386918[net.sf.json.JsonNode@787bb290]
可以看出,如果字段类型为强类型时,转换时可以自动转换为原类型,但如果属性为List时,默认转换时会将List中的对象转换为的对象,此时可以使用为属性指定类型,这样就可以得到我们希望的结果 。
5.在线API链接
【json-lib中Json对象与Java Bean对象的转换控制】主要的配置类中,查看API时需注意配置项是Java→JSON,还是JSON→Java
- 中东部新一轮雨雪又又又来了 寒潮再来今夜起有剧烈降温
- 班昭续汉书 班昭续汉书中写马融的目的
- 中晋最新消息2020年_2020年连云港房价走势最新消息及未来趋势预测分析
- 2023发布 Euro-NCAP-HWA测试流程中文版V1.1
- 国产中间件,向左还是向右?
- 全国中职网络安全B模块之国赛题远程代码执行渗透测试 //PHPstudy的后门漏
- cpu中的指令计数器的作用
- 山东遭遇强降雪 济南中小学今天停课一天
- 双中台在医疗 | 复旦中山医院钱琨:数据中台是迈向“未来医院”的第一步
- 无代码平台助力中山医院搭建“智慧化管理体系”,实现智慧医疗