树形json的删改操作

公司上周五突然来了个任务,来到这家公司这么久第一次被要求做的任务就是做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。这个知识点一直都知道,只是在编程的时候却忽略了,离独当一面的程序猿还很远哪。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值