json-lib中Json对象与Java Bean对象的转换控制

在Java中操作Json对象时,经常遇到以下几种情况:

Json字符串与Json对象的转换

Json对象与Java对象的转换

以下使用json-lib第3方工具进行讲解

其中Java对象→Json对象→Json字符串用的较多,其操作也较为简单,

1.Java对象→Json对象

	private static void JavaObj2JsonObj() {
		//将Java对象转换成Json对象,转换后的类型为JSONObject
		JSONObject jsonObj = JSONObject.fromObject(javaObj);
		//对象Map对象,也使用JSONObject的putAll方法将map内的键值对转换为Json对象中的属性-值
		HashMap<String,Object> map = new HashMap<String, Object>();
		map.put("tel", "13566662222");
		jsonObj.putAll(map);
		//put方法可设置一个属性值
		jsonObj.put("key","123");
		//element方法返回Json对象本身,可以进行串联调用
		jsonObj.element("name", "java").element("length", 4);
		List<Object> list = new ArrayList<Object>();
		list.add(javaObj);
		//声明一个数组对象
		JSONArray jsonAry = new JSONArray();
		jsonAry.addAll(list);
		jsonAry.add(javaObj);
		System.out.println(jsonObj);
		System.out.println(jsonAry);
	}

输出结果如下:

{"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对象转换时,相对较为简单,但对日期这类较特殊的对象进行转换时,默认会转换成一个JSONObject对象,在转换为Json对象时会按一般对象进行处理,转换后的内容可读性较差,如何将日期对象转换为可读性强的日期字符串呢?这就要用到JsonConfig类了,使用JsonConfig类可以指定转换规则,如果想将日期对象转换为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());
	}

PropertyFilter接口中仅有一个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字符串最简单,默认使用toString方法即可返回字符串,如果要使用缩进模式输出,则在toString中增加缩进数量的参数,直接看代码吧:

	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对象比较简单,只需要调用JSONObject和JSONArray对象的静态方法 fromObject,传入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对象属性过滤

转换时如果不需要某些属性,可以使用JsonConfig对象进行过滤

	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对象

JSONObject 对象的静态方法toBean可以将一个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类

发现通过JsonNode类的对象转换成Json对象后,再用toBean方法转换为Java对象时,变成了MorphDynaBean,如何将转换后的对象仍变成JsonNode呢?还是要使用JsonConfig对象

	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的警告,提示timezoneOffset和day属性没有写方法,如何消除这些警告呢?可以在JsonConfig中增加属性过滤

	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对象时要进行特殊的处理,要注册日期转换对象DateMorpher,此行代码只需在toBean方法执行前执行即可,放在静态代码块执行也可以。

	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<JsonNode>());
		jmn.getChildren().add(javaObj);
		JSONObject json = JSONObject.fromObject(jmn);
		System.out.println(json.toString());
		JsonConfig cfg = new JsonConfig();
		cfg.setRootClass(JsonMainNode.class);
		Object obj = JSONObject.toBean(json, cfg);
		System.out.println(obj);
		System.out.println(((JsonMainNode)obj).getJsonNode());
		System.out.println(((JsonMainNode)obj).getChildren());
		Map<String, Class> cmap = new HashMap<String, Class>();
		cmap.put("children", JsonNode.class);
		cfg.setClassMap(cmap);
		obj = JSONObject.toBean(json, cfg);
		System.out.println(obj);
		System.out.println(((JsonMainNode)obj).getJsonNode());
		System.out.println(((JsonMainNode)obj).getChildren());
	}

输出结果如下:

 

{"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@3f57fb52
net.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@528acf6e
net.sf.json.JsonNode@17386918
[net.sf.json.JsonNode@787bb290]

可以看出,如果字段类型为强类型时,转换时可以自动转换为原类型,但如果属性为List时,默认转换时会将List中的对象转换为MorphDynaBean的对象,此时可以使用setClassMap为属性指定类型,这样就可以得到我们希望的结果。

5.在线API链接

http://tool.oschina.net/apidocs/apidoc?api=json-lib2.4

主要的配置类JsonConfig中,查看API时需注意配置项是Java→JSON,还是JSON→Java

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shuaijie506

您的打赏是我继续分享的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值