公司让开发一个解析现有模板的的json类。
json模板是这样样子的多层嵌套json对象,本来要解决jsonObect和jsonArray两种类型的对象,但是仔细核对过后发现,在业务中并没有使用到jsonArray这种类型的对象。所以我先做了解析多层嵌套JsonObject的JsonObject对象。
先开看一下我们要使用到的Json模版
{
"一班":{
"座位2":{
"studentAge":13,
"studentName":"李四"
},
"座位1":{
"studentAge":12,
"studentName":"张三"
}
},
"二班":{
"座位3":{
"studentAge":14,
"studentName":"王五"
},
"座位4":{
"studentAge":15,
"studentName":"赵六"
}
}
}
那么这里我使用的嵌套是两层嵌套 第一级是班,第二级是座位但是在实际生产过程中,并不知道有多少级Json嵌套。那么就需要自动的来确定Json嵌套的层数。先来看我的Util类吧。
package com.kx.www;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson.JSONObject;
public class JsonUtils {
private String jsonMode="";
/**
* 单个key 修改 json模版
* @param jsonMode
* jsonString模板
* @param key
* 传入XX.XX.XX.AA(标识要修改那个字段)
* @param value
* json模版 String 字符串
* @return
* json模版 String 字符串 如果key值在模版中有那么返回修改后的模版,如果key在模版中没有那么返回传入的模版
*/
public String PutNewValue(String jsonMode, String key, String value) {
JSONObject jsonObject = JSONObject.parseObject(jsonMode);
// 把接收到的json格式的字符串模板转换为json对象
// 切分 遍历key 拿出前面节点 和最后一个key值
String[] keys = key.split("\\.");
List<JSONObject> list = new ArrayList<JSONObject>();
list.add(jsonObject);
for (int i = 0; i < keys.length - 1; i++) {
try {
jsonObject = jsonObject.getJSONObject(keys[i]);
} catch (Exception e) {
return jsonMode;
}
list.add(jsonObject);
}
jsonObject.put(keys[keys.length - 1], value);
for (int i = keys.length - 2; i >= 0; i--) {
list.get(i).put(keys[i], list.get(i + 1));
}
jsonObject = list.get(0);
return formatJson(jsonObject.toString());
}
/**
* 多个key值 单个value值修改json模版
* @param jsonMode
* jsonString模板
* @param keys
* 传入XX.XX.XX.AA(标识要修改那个字段) 这样形式的String数组
* @param value
* 要修改的值
* @return
* json模版 String 字符串 如果key值在模版中有那么返回修改后的模版,如果key在模版中没有那么返回传入的模版
*/
public String PutNewValue(String jsonMode, String[] keys, String value) {
String result = jsonMode;
for (String key : keys) {
result = PutNewValue(result, key, value);
}
return result;
}
/**
* 多个key值 多个value值批量修改 json模版
* @param jsonMode
* @param map
* key传入XX.XX.XX.AA(标识要修改那个字段) value与key对应的value值
* @return
*/
public String PutNewValue(String jsonMode,Map<String, String> map) {
String result = jsonMode;
for (String key :map.keySet()) {
result = PutNewValue(result, key, map.get(key));
}
return result;
}
/**
* 格式化Json串
*
* @param jsonStr
* @return
*/
public static String formatJson(String jsonStr) {
if (null == jsonStr || "".equals(jsonStr)) {
return "";
}
StringBuilder sb = new StringBuilder();
char last = '\0';
char current = '\0';
int indent = 0;
for (int i = 0; i < jsonStr.length(); i++) {
last = current;
current = jsonStr.charAt(i);
switch (current) {
case '{':
case '[':
sb.append(current);
sb.append('\n');
indent++;
addIndentBlank(sb, indent);
break;
case '}':
case ']':
sb.append('\n');
indent--;
addIndentBlank(sb, indent);
sb.append(current);
break;
case ',':
sb.append(current);
if (last != '\\') {
sb.append('\n');
addIndentBlank(sb, indent);
}
break;
default:
sb.append(current);
}
}
return sb.toString();
}
/**
* 添加space
*/
private static void addIndentBlank(StringBuilder sb, int indent) {
for (int i = 0; i < indent; i++) {
sb.append('\t');
}
}
}
代码中规定好了传入key的规则然后解析字符串让其从层json对象中取出想要对象或者值然后再逐层放回去。
后面我有尝试这做修改jsonArray中的数据的util类和上面的模板类似,不过在其中加入了JsonArray不再是单纯的jsonObject类型的数据。
{
"一班": {
"座位2": {
"studentAge": 13,
"studentName": "李四"
},
"座位1": {
"studentAge": 12,
"studentName": "张三"
}
},
"二班": {
"座位3": {
"studentAge": 14,
"studentName": "王五"
},
"座位4": {
"studentAge": 15,
"studentName": "赵六"
}
},
"三班": [{
"studentAge": 14,
"studentName": "王五"
}, {
"studentAge": 15,
"studentName": "赵六"
}]
}
三班没有二级JosnObject 而是一个Json数组,我写的util是在下面。
/**
* 确定是JsonObject还是JsonArray
* @param jsonObject
* @param firstkey
* @return
*/
private String ArrOrObj(JSONObject jsonObject, String firstkey) {
try {
Object object = jsonObject.getJSONObject(firstkey);
if (object instanceof JSONObject) {
return "OBJECT";
}
} catch (Exception e) {
return "ARRAY";
}
return "ERROR";
}
/**
* 这个代码可能用不了只是提供一种思路吧
* @param jsonMode
* @param key
* @param value
* @return
*/
public String PutNewValue1(String jsonMode,String key,String value) {
//把接收到的json格式的字符串模板转换为json对象
JSONObject jsonObject = JSONObject.parseObject(jsonMode);
JSONArray jsonArray = new JSONArray();
//切分 遍历key 拿出前面节点 和最后一个key值
String [] keys = key.split("\\.");
List<JSONObject> list = new ArrayList<JSONObject>();
list.add(jsonObject);
for (int i = 0; i < keys.length-1; i++) {
String result = ArrOrObj(jsonObject,keys[i]);
try {
//就得判断这个keys是Object还是Array
if(result == "ARRAY") {
jsonArray = jsonObject.getJSONArray(keys[i]);
String ja = jsonArray.toString();
List list1 = JSONObject.parseArray(ja, String.class);
//写到这 就出现了我想不到解决办法的问题,那么,在我上面的模板中,怎么确定待修改的数据是list1中那个对象的值.
//想到这里 如果说想要知道是那个对象的值.那么在传入key的时候就需要指定. 那么用户用户,或者说其他编码人员怎么知道,就将key 的规则破坏.
}else if(result == "OBJECT") {
jsonObject=jsonObject.getJSONObject(keys[i]);
}
} catch (Exception e) {
System.out.println("模版文件中找不到节点,或者没有该字段");
}
list.add(jsonObject);
}
jsonObject.put(keys[keys.length-1], value);
for (int i = keys.length-2; i >=0; i--) {
list.get(i).put(keys[i] , list.get(i+1));
}
jsonObject = list.get(0);
return formatJson(jsonObject.toString());
}
首先的判断这个Json对象中的对象是Object还是Array 那么确定这个之后才能进行下面的操作。