java递归实现动态解析json字符串未知key的方法

1、递归一

有的时候我们需要解析未知的json。或者说是动态的json。那么我们并不知道key具体是多少,或者说key不是固定的。这时候就需要解析动态key的方法。

这个方法是我在实现解析前台传入的json时所需要的。因为每个界面的前台传的是json是不固定的。如果真对每一个页面所传的数据都单独进行一次解析,那么太麻烦了。所以需要一个通用的解析方式。将其解析到map中。那么只需要调用该方法,就能获取到前台所传json对于的map。

在网上搜了一会,找不到我想要的方法,即不和我心意,代码又不给全。所以自己测试了一个简单的代码。我是使用递归实现的,代码简单。就不一一讲解了,如果还有不清楚的,请留言。

package jsonTest;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import net.sf.json.JSONObject;

public class JsonTest {
	public static void main(String[] args) {
	    //测试字符串
		String test = "{a:1,b:2,c:3,d:{q:4,w:5,e:6,y:{o:7,p:8}}}";
		Map res = new HashMap();
		//递归遍历解析方法
		iteraJson(test,res);
		//解析得到最终map后,遍历该map输出值
		Set keySet = res.keySet();
		Iterator iterator = keySet.iterator();
		while(iterator.hasNext()){
			String key = iterator.next().toString();
			Object val = res.get(key);
			System.out.println(key+":"+val.toString());
		}
	}
	//递归遍历解析方法
	public static boolean iteraJson(String str,Map res){
	  //因为json串中不一定有逗号,但是一定有:号,所以这里判断没有则已经value了
		if(str.toString().indexOf(":") == -1){
			return true;
		}
		JSONObject fromObject = JSONObject.fromObject(str);
		Iterator keys = fromObject.keys();
		while(keys.hasNext()){
			String key = keys.next().toString();
			Object value = fromObject.get(key);
			if(iteraJson(value.toString(),res)){
				res.put(key, value);
			}
		}
		return false;
	}
}

效果如下:
这里写图片描述

2、递归二

上面的递归方式只支持没有包含数组格式的json字符串。例如:

		String test = "{a:1,b:[1,2,3],c:3,d:{q:4,w:5,e:6,y:{o:7,p:8}},arry:[{name1:'joker',age:30},{name2:'dd',age:20},{name3:'bb',age:10}]}";

b:[1,2,3] 这个数组是正规数组,不是json数组,不需要解析。
arry:[{name1:‘joker’,age:30},{name2:‘dd’,age:20},{name3:‘bb’,age:10}]。这个是json数组,需要继续解析。
要实现这两个格式的兼容。下面的代码能够实现:

	public static boolean iteraJsonOrArray(String source,Map map){
		if(source.indexOf(":") == -1){
			return true;
		}
		JSONObject fromObject = JSONObject.fromObject(source);
		Iterator keys = fromObject.keys();
		while(keys.hasNext()){
			String key = keys.next().toString();
			Object value = fromObject.get(key);
			String val = value.toString();
			if(val.indexOf("[{") == -1){
				//说明不存在数组json即格式为:"[{" 开头的数据。可以允许是[10,11,12]的非json数组
				if(val.indexOf(":") == -1  || val.matches("[\\d]{4}-[\\d]{2}-[\\d]{2}\\s[\\d]{2}:[\\d]{2}:[\\d]{2}"){
				//当字符串中不存在:说明已经是值了,如果存在:也可能是日期类型的数据,所以用正则表达式匹配,如果是日期,就直接放入Map中
					map.put(key, val);
				}else{
					iteraJson(val,map);
				}
			}else if(val.indexOf("[{") != -1){
				//说明存在数组json即格式为:[{开头的json数组
				if(val.indexOf("[{") == 0){
					//说明当前value就是一个json数组
					//去除[括号
					String jsons = val.substring(1, val.lastIndexOf("]"));//得到数据格式为:{...},{...},{...}
					//把上面得到jsons分割成数组
						//因为数据格式为{name:joker,age:20},{...},{...},所以不能用逗号分割。否则会变"{name:joker" "age:20}"
						//使用正则表达式把},{替换成}|{
					jsons = jsons.replaceAll("\\}\\s?,\\s?\\{", "}|{");
					String[] split = jsons.split("\\|");
					for(int i = 0; i < split.length;i++){
						iteraJsonOrArray(split[i],map);//符合当前递归条件
					}
					
				}else{
					//说明value可能是一个json,这个json中任然包含数组。例如:{inner:[{a:1,b:2,c:3}]}
					iteraJsonOrArray(val,map);//符合当前递归条件
				}
			}
			
		}
		
		return false;
	}

把 iteraJsonOrArray 方法写到递归一中的代码里。因为这个方法里调用了递归一中的iteraJson来解析没包含任何数组类型的json串。

执行代码

		String test = "{a:1,b:[1,2,3],c:3,d:{q:4,w:5,e:6,y:{o:7,p:8}},arry:[{name1:'joker',age:30},{name2:'dd',age:20},{name3:'bb',age:10}]}";
		Map res = new HashMap();
		iteraJsonOrArray(test,res);
		Set keySet = res.keySet();
		Iterator iterator = keySet.iterator();
		while(iterator.hasNext()){
			String key = iterator.next().toString();
			Object val = res.get(key);
			System.out.println(key+":"+val.toString());
		}

效果如下:
这里写图片描述

**注意:**上图中 的name我分为name1,name2,name3。上图只有一个age。因为key重名了,所以放入map中自然会被覆盖掉。如果三个name一样,最后只能得到一个name一个age.

**

3、递归三

**
递归二的方式可以实现大部分json格式。但是遇到key相同的json就不好保存数据。
比如:{arry:[{name:joker,age:15},{name:jake,age:20},{name:mari,age:25}]};这种格式用递归二的话,放入map中,最后只得到name:mari 和 age:25。

所以我们需要把所有的值都保存起来,那么就不是放入map中,而是list中了。
如下图,在递归二中创建临时tempmap和list。然后把list添加到最终map中。
这里写图片描述

输出结果为:
这里写图片描述
这样就可以接受前台传到后台的json数据。这个json数据可以包含表单的值和表格的值一起。

好的,以下是 Java 代码示例来获取 JSON 字符串的所有 key 和 value: ```java import org.json.simple.JSONObject; import org.json.simple.JSONArray; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; public class JsonUtil { public static void main(String[] args) throws ParseException { String jsonStr = "{\"name\":\"John\", \"age\":30, \"car\":null, \"hobbies\":[\"reading\",\"music\"]}"; JSONObject jsonObj = (JSONObject) new JSONParser().parse(jsonStr); JSONObject result = new JSONObject(); getKeysAndValues(jsonObj, result); System.out.println(result.toJSONString()); } private static void getKeysAndValues(JSONObject jsonObj, JSONObject result) { for (Object key : jsonObj.keySet()) { Object value = jsonObj.get(key); result.put(key, value); if (value instanceof JSONObject) { getKeysAndValues((JSONObject) value, result); } else if (value instanceof JSONArray) { getKeysAndValuesFromJsonArray((JSONArray) value, result); } } } private static void getKeysAndValuesFromJsonArray(JSONArray jsonArray, JSONObject result) { for (Object obj : jsonArray) { if (obj instanceof JSONObject) { getKeysAndValues((JSONObject) obj, result); } else if (obj instanceof JSONArray) { getKeysAndValuesFromJsonArray((JSONArray) obj, result); } } } } ``` 这个示例使用了 JSON.simple 库来解析 JSON 字符串。它递归遍历 JSON 对象和数组,并将所有 key 和 value 存储在一个新的 JSONObject 中。你可以根据你的需要修改这个示例,比如将 JSONObject 替换成 Map,等等。注意,这个示例假设 JSON 中没有循环引用,否则会进入死循环。
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值