公司上周五突然来了个任务,来到这家公司这么久第一次被要求做的任务就是做json数据的删改操作,不过我很喜欢算法,所以对我而言这是个再有趣不过的任务,下面贴出我的算法与大家共享,初出茅庐,第一次是为了工作写算法,边界考虑有失周全的地方请提出来。
package com.hk13a;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
/*
*
*
*
*/
public class JsonTreeUtils {
public static final String SEPARATOR = "&";
/**
* 修改数据
* @param jsonStr 要修改的json串
* @param altMap 修改内容
* @return 修改成功返回修改后json串,修改失败返回原json串
*/
public static String alter(String jsonStr, Map<String, Object> altMap) throws JSONException{
if(jsonStr == null || jsonStr.equals("")){
throw new JSONException("Json must be valid");
}
return new JsonTreeUtils().traversal(jsonStr, altMap, "alter");
}
/**
* 删除数据
* @param jsonStr 要处理的json串
* @param id 删除的ID
* @return 删除成功返回修改后json串,失败返回原json
*/
public static String remove(String jsonStr, String id) throws JSONException{
if(jsonStr == null || jsonStr.equals("")){
throw new JSONException("Json must be valid");
}
Map<String, Object>altMap = new HashMap<>();
altMap.put("id", id);
return new JsonTreeUtils().traversal(jsonStr, altMap, "delete");
}
@SuppressWarnings("unchecked")
public Map<String, Object> toMap(String jsonStr){
return (Map<String, Object>)JSONObject.fromObject(jsonStr);
}
/**
* 截取jsonStr
* @param jsonStr
* @return
*/
public String adjust(String jsonStr){
jsonStr = jsonStr.trim();
if(jsonStr.endsWith("]")) jsonStr = jsonStr.substring(1, jsonStr.lastIndexOf("]"));
while(jsonStr.startsWith(",")) jsonStr = jsonStr.substring(1, jsonStr.length());
return jsonStr;
}
/**
* E:/jsonFile.json
* 读取json字符串
* @return
*/
public static String read(String path){
String fullFileName = path;
File file = new File(fullFileName);
Scanner scanner = null;
StringBuilder buffer = new StringBuilder();
try {
scanner = new Scanner(file, "utf-8");
while (scanner.hasNextLine()) {
buffer.append(scanner.nextLine());
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
} finally {
if (scanner != null) {
scanner.close();
}
}
return buffer.toString();
}
/**
* 遍历数据
* @param jsonStr
*/
public String traversal(String jsonStr, Map<String, Object> altMap, String type){
String temp = adjust(jsonStr);
temp = replaces(temp);
String[] jsonList = temp.split(SEPARATOR);
String tempp = "";
for(String json : jsonList){
json = adjust(json);
Map<String, Object> map = toMap(json);
List<Object> keys = Arrays.asList(map.keySet().toArray());
for(Object k : keys){
String key = (String)k;
if("id".equals(key)){
if(altMap.get(key) != null && altMap.get(key).equals((String)map.get(key))){
//操作数据
//修改数据
switch(type)
{
case "alter":
map = alter(map, altMap);
jsonStr = jsonStr.replace(json, map.toString());
return jsonStr;
case "delete":
jsonStr = delete(jsonStr, json);
return jsonStr;
}
}
}
}
for(Object k : keys){
String key = (String)k;
if("data".equals(key)){
tempp = traversal(map.get("data").toString(), altMap, type);
jsonStr = jsonStr.replace(map.get("data").toString(), tempp);
}
if("nodes".equals(key)){
tempp = traversal(map.get("nodes").toString(), altMap, type);
jsonStr = jsonStr.replace(map.get("nodes").toString(), tempp);
}
}
}
return jsonStr;
}
/**
* 分隔数据
* @param jsonStr
* @return
*/
public String replaces(String jsonStr){
int count = 0;
String retStr = "";
String[] s = jsonStr.split("");
for(int i=0; i<s.length; i++){
if("{".equals(s[i])){
count++;
}
if("}".equals(s[i])){
count--;
}
if(count == 0){
if(s.length > i+1)
s[i] = "}" + SEPARATOR;
retStr = retStr.concat(s[i]);
i = i+1;
continue;
}
retStr = retStr.concat(s[i]);
}
return retStr;
}
/**
* 修改数据
* @param origMap
* @param altMap
* @return
*/
public Map<String, Object> alter(Map<String, Object> origMap, Map<String, Object> altMap){
Object[] keys = altMap.keySet().toArray();
for(Object key : keys){
if(altMap.get(key) != null && !"".equals(altMap.get(key))){
origMap.replace((String) key, altMap.get(key));
}
}
//模拟修改
// origMap.replace("type", "大数据");
return origMap;
}
public String delete(String jsonStr, String json){
jsonStr = jsonStr.replace("," + json, "");
jsonStr = jsonStr.replace(json + ",", "");
jsonStr = jsonStr.replace(json, "");
return jsonStr;
}
}
有几点瑕疵要提的,第一,数据不能包含不成对的”{” 或”}”,因为分隔算法受限,分隔符我设定为&,可以按需求修改,甚至可以用一个随机字符串代替,还有就是adjust方法应该捕获并抛出一个JSONException,这个我没加上。因为感觉我写的算法公司也不会用上,毕竟一个新手,思考不周导致些许漏洞就不好了。另:有什么值得提出来的,设计不合理的,请务必提出来讨论,谢谢大家。
2017/3/30
这里提出一个优化点,是我之前没想到,再看security源码的时候想到的。字符串需要修改的时候,特别是分隔json串的时候,最好采用StringBuffer,因为如果直接使用String,String是不可变类型,每次都会生成一个新的String,这会浪费大量的内存。而StringBuffer是可变类型,只有调用它的toString的时候会生成一个新的String。这个知识点一直都知道,只是在编程的时候却忽略了,离独当一面的程序猿还很远哪。