使用FastJson重寫JsonUtil工具,根據路徑獲取JSON值


import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;
import com.alibaba.fastjson.serializer.SerializerFeature;

/**
 * Json 工具類 使用FastJson重新寫了代碼,性能有大幅度提升,並且減少了內存和CPU消耗
 */
public class JsonUtil {
    private static ConcurrentHashMap<String, String> pathCache = new ConcurrentHashMap<String, String>(1024, 0.75f, 1);

    public static JsonUtil instance = new JsonUtil();
    
    static {
        JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.DisableCircularReferenceDetect.getMask();
    }

    public static String getStringValue(JSONObject jsonData, String path) {
        Object val = getValue(jsonData, path, false);
        return val != null ? val.toString() : null;
    }

    public static Object getValue(JSONObject jsonData, String path, boolean jsonPath_flag) {
        try {
            if (jsonPath_flag) {
                return JSONPath.eval(jsonData, path);
            }
            else {
                String path_new = transferToJsonPath(path);
                return JSONPath.eval(jsonData, path_new);
            }
        }
        catch (Exception e) {
            return null;
        }
    }

    /**
     * 從JONSObject 中解析列表,如果列表爲空,返回新的ArrayList
     * 
     * @param json
     * @param path
     * @return
     */
    @SuppressWarnings("rawtypes")
	public static List getSubListFromJSON(JSONObject jsonData, String path) {
        List value = (List) getValue(jsonData, path, false);
        return value != null ? value : new ArrayList();
    }

    // 轉化成符合jsonpath格式的路徑
    public static String transferToJsonPath(String path) {
        String path_inner = pathCache.get(path);

        if (path_inner == null) {
            path_inner = path.replaceAll("\\.([0-9]+)([\\.]?)", "[$1\\]$2");
            pathCache.putIfAbsent(path, path_inner);
        }

        return path_inner;
    }

    // will use the fastjson function to modify the json content
    // 使用FastJson的set方法來設置值,如果成功則返回true,否則 false
    public static boolean setValueByJsonPath(JSONObject rootObject, String path, Object value) {
        try {
            JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.DisableCircularReferenceDetect.getMask();
            JSONPath jsonpath = JSONPath.compile(path);
            return jsonpath.set(rootObject, value);
        }
        catch (Exception e) {
            return false;
        }
    }

    // 使用Jsonpath格式設置值 path= a.b[0].c.d[0].e
    public static boolean setValue(JSONObject rootObject, String path, Object value) {
        return setValue(rootObject, path, value, true);
    }
    
    @SuppressWarnings("rawtypes")
    // 設置Json裏面的內容,如果Json裏面沒有這個值,則生成這個key
    public static boolean setValue(JSONObject rootObject, String path, Object value, boolean jsonPath_format) {
    	  String parentPath = jsonPath_format ? path : transferToJsonPath(path);

          String currentPath = "";
          String key = "";
          Object valueObj = value;

          boolean result = false;
          boolean lastArrayNode = false;

          while (parentPath != null && !(result = setValueByJsonPath(rootObject, parentPath, valueObj))) {

              int indexPos = parentPath.lastIndexOf(".");

              currentPath = parentPath.substring(indexPos + 1);

              if (indexPos >= 0) {
                  parentPath = parentPath.substring(0, indexPos);
              }
              else {
                  int indexParentPathPos2 = parentPath.indexOf('[');
                  if (indexParentPathPos2 > 0) {
                      lastArrayNode = true;
                  }
                  parentPath = null;
              }

              int indexPos2 = currentPath.indexOf('[');
              if (indexPos2 > 0) {
            key = currentPath.substring(0, indexPos2);

                  ArrayList tempObj = null;
                  if (parentPath != null) {
                      Object obj = getValue(rootObject, parentPath + "." + key, true);
                      if (!"".equals(obj)) {
                          tempObj = (ArrayList) obj;
                      }
                  }
                  else {
                      Object obj = getValue(rootObject, key, true);
                      if (!"".equals(obj)) {
                          tempObj = (ArrayList) obj;
                      }
                  }

                  if (tempObj == null) {
                      tempObj = new ArrayList();
                  }

                  tempObj.add(valueObj);
                  valueObj = tempObj;
              }
              else {
                  key = currentPath;
              }

              if (lastArrayNode) {
                  rootObject.put(key, valueObj);
              }
              else {
                  JSONObject tempObj = null;
                  Object obj = getValue(rootObject, parentPath, true);
                  if (!"".equals(obj)) {
                      tempObj = (JSONObject) obj;
                  }

                  if (tempObj == null) {
                      tempObj = new JSONObject();
                  }
                  tempObj.put(key, valueObj);
                  valueObj = tempObj;
              }
          }

          return result;
    }

    private static JSONObject merge(JSONObject target, Object source) {
        if (source == null) return target;
        if (source instanceof JSONObject) return merge(target, (JSONObject) source);
        throw new RuntimeException("JSON megre can not merge JSONObject with " + source.getClass());
    }

    private static JSONArray merge(JSONArray target, Object source) {
        if (source == null) return target;
        if (target instanceof JSONArray) return merge(target, (JSONArray) source);
        target.add(source);
        return target;
    }

    private static JSONArray merge(JSONArray target, JSONArray source) {
        target.addAll(source);
        return target;
    }

    private static JSONArray mergeItemContent(JSONArray target, JSONArray source) {
        JSONArray mergeResult = new JSONArray();
        for (int i = 0; i < source.size(); i++) {
            JSONObject value1 = (JSONObject) target.get(i);
            JSONObject value2 = (JSONObject) source.get(i);
            mergeResult.add(merge(value1, value2));
        }
        return mergeResult;
    }

    // 合併另個json
    public static JSONObject merge(JSONObject target, JSONObject source) {
        return merge(target, source, true, false);
    }

    public static JSONObject merge(JSONObject target, JSONObject source, boolean overwrite) {
        return merge(target, source, true, true);
    }

    /*
     * overwrite: 當處理數組時,如果爲true使用新的數組完全覆蓋老的數組。 當爲false時,在老的數組尾部添加新的元素
     * appendItemFlag: 當爲true時,source裏面的可以如果沒有在target存在,則添加到target裏面。
     * 當爲false時,則不添加,這樣意味着只會使用source裏面的值去替換target對應的key
     */
    public static JSONObject merge(JSONObject target, JSONObject source, boolean overwrite, boolean appendItemFlag) {
        if (source == null) return target;

        for (String key : target.keySet()) {
            Object value1 = target.get(key);
            Object value2 = source.get(key);
            if (value2 == null) continue;
            if (value1 instanceof JSONArray) {
                if (overwrite)
                    target.put(key, value2);
                else
                    target.put(key, merge((JSONArray) value1, value2));
                continue;
            }

            if (value1 instanceof JSONObject) {
                target.put(key, merge((JSONObject) value1, value2));
                continue;
            }

            if (value1.equals(value2)) {
                continue;
            }
            else if (overwrite) {
                target.put(key, value2);
                continue;
            }

            if (value1.getClass().equals(value2.getClass())) throw new RuntimeException(
                    "JSON merge can not merge two " + value1.getClass().getName() + " Object together");
            throw new RuntimeException(
                    "JSON merge can not merge " + value1.getClass().getName() + " with " + value2.getClass().getName());
        }

        if (appendItemFlag) {
            for (String key : source.keySet()) {
                if (target.containsKey(key)) continue;
                target.put(key, source.get(key));
            }
        }
        return target;
    }

    /**
     * 
     * @param json
     * @param path
     * @return
     */
    public static Object getObjectFromJson(JSONObject json, String path) {
        return JsonUtil.getValue(json, path, false);
    }

    /**
     * 支持多級添加
     * 
     * @param jsonData
     * @param path
     * @param jsonValue
     * 
     */
    public static void setStringValue(JSONObject jsonData, String path, String jsonValue) {
        setValue(jsonData, path, jsonValue, false);
    }

    public static boolean isNumeric(String str) {
        Pattern pattern = Pattern.compile("[0-9]*");
        Matcher isNum = pattern.matcher(str);
        if (!isNum.matches()) {
            return false;
        }
        return true;
    }

    public static String getStringValue_old(JSONObject jsonData, String path) {
        String jsonValue = null;
        try {
            String[] strPath = StringUtils.split(path.trim(), "\\.");
            int length = strPath.length;
            if (length == 0) {
                jsonValue = jsonData.getString(path);
            }
            else {
                for (int i = 0; i < length; i++) {
                    if (i + 1 < length && isNumeric(strPath[i + 1])) {
                        JSONArray arr = JSONArray.parseArray(jsonData.getString(strPath[i]));
                        jsonValue = arr.getString(Integer.parseInt(strPath[i + 1]));
                        jsonData = JSON.parseObject(arr.get(Integer.parseInt(strPath[i + 1])).toString());
                        i++;
                    }
                    else {
                        jsonValue = jsonData.getString(strPath[i]);
                        if (i < length - 1) {
                            jsonData = JSON.parseObject(jsonData.getString(strPath[i]));
                        }
                    }
                }
            }
        }
        catch (Exception e) {
            jsonValue = null;
        }
        return jsonValue;
    }

    public static void setStringValue_old(JSONObject jsonData, String path, String jsonValue) {
        String[] strPath = StringUtils.split(path.trim(), "\\.");
        int length = strPath.length;
        String pathTemp = path;
        Map<String, Object> mapTemp = null;
        JSONObject o = null;
        Object objValue = jsonValue;
        try {

            for (int i = 0; i < length - 1; i++) {
                if (isNumeric(strPath[length - i - 1])) {

                    pathTemp = pathTemp.substring(0, pathTemp.lastIndexOf("."));
                    JSONArray arr = JSONArray.parseArray(getStringValue(jsonData, pathTemp));
                    pathTemp = pathTemp.substring(0, pathTemp.lastIndexOf("."));
                    String value = getStringValue_old(jsonData, pathTemp);
                    if (arr == null) {
                        arr = new JSONArray(Integer.parseInt(strPath[length - i - 1]) + 1);
                        arr.add(Integer.parseInt(strPath[length - i - 1]), objValue);
                        mapTemp = new HashMap<String, Object>();
                        mapTemp.put(strPath[length - i - 2], arr);
                        if (value == null || "".equals(value)) {
                            o = new JSONObject();
                            o.putAll(mapTemp);
                        }
                        else {
                            o = JSON.parseObject(value);
                            o.putAll(mapTemp);
                        }

                    }
                    else {
                        if (arr.size() <= Integer.parseInt(strPath[length - i - 1])) {
                            arr.add(Integer.parseInt(strPath[length - i - 1]), objValue);
                        }
                        else {
                            arr.set(Integer.parseInt(strPath[length - i - 1]), objValue);
                        }
                        mapTemp = new HashMap<String, Object>();
                        mapTemp.put(strPath[length - i - 2], arr);
                        if (value == null || "".equals(value)) {
                            o = new JSONObject();
                            o.putAll(mapTemp);
                        }
                        else {
                            o = JSON.parseObject(value);
                            o.putAll(mapTemp);
                        }
                    }
                    objValue = o;
                    i++;

                }
                else {

                    mapTemp = new HashMap<String, Object>();
                    mapTemp.put(strPath[length - i - 1], objValue);
                    pathTemp = pathTemp.substring(0, pathTemp.lastIndexOf("."));
                    String value = getStringValue_old(jsonData, pathTemp);
                    if (value == null || "".equals(value)) {
                        o = new JSONObject();
                        o.putAll(mapTemp);
                    }
                    else {
                        o = JSON.parseObject(value);
                        o.putAll(mapTemp);
                    }
                    objValue = o;
                }
            }
            mapTemp = new HashMap<String, Object>();
            mapTemp.put(strPath[0], objValue);
            jsonData.putAll(mapTemp);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Convert a JSONObject into a well-formed, element-normal XML string.
     * 
     * @param object
     *            A JSONObject.
     * @return A string.
     * @throws JSONException
     */
    public static String toXMLString(Object object) throws JSONException {
        return toXMLString(object, null);
    }

    public static String escape(String string) {
        StringBuilder sb = new StringBuilder(string.length());
        for (int i = 0, length = string.length(); i < length; i++) {
            char c = string.charAt(i);
            switch (c) {
                case '&':
                    sb.append("&amp;");
                    break;
                case '<':
                    sb.append("&lt;");
                    break;
                case '>':
                    sb.append("&gt;");
                    break;
                case '"':
                    sb.append("&quot;");
                    break;
                case '\'':
                    sb.append("&apos;");
                    break;
                default:
                    sb.append(c);
            }
        }
        return sb.toString();
    }

    /**
     * Convert a JSONObject into a well-formed, element-normal XML string.
     * 
     * @param object
     *            A JSONObject.
     * @param tagName
     *            The optional name of the enclosing tag.
     * @return A string.
     * @throws JSONException
     */
    public static String toXMLString(Object object, String tagName) throws JSONException {
        StringBuilder sb = new StringBuilder();
        int i;
        JSONArray ja;
        JSONObject jo;
        String key;
        Iterator<String> keys;
        int length;
        String string;
        Object value;
        if (object instanceof JSONObject) {

            // Emit <tagName>

            if (tagName != null) {
                sb.append('<');
                sb.append(tagName);
                sb.append('>');
            }

            // Loop thru the keys.

            jo = (JSONObject) object;
            keys = jo.keySet().iterator();
            while (keys.hasNext()) {
                key = keys.next();
                value = jo.get(key);
                if (value == null) {
                    value = "";
                }
                string = value instanceof String ? (String) value : null;

                // Emit content in body

                if ("content".equals(key)) {
                    if (value instanceof JSONArray) {
                        ja = (JSONArray) value;
                        length = ja.size();
                        for (i = 0; i < length; i += 1) {
                            if (i > 0) {
                                sb.append('\n');
                            }
                            sb.append(escape(ja.get(i).toString()));
                        }
                    }
                    else {
                        sb.append(escape(value.toString()));
                    }

                    // Emit an array of similar keys

                }
                else if (value instanceof JSONArray) {
                    ja = (JSONArray) value;
                    length = ja.size();
                    for (i = 0; i < length; i += 1) {
                        value = ja.get(i);
                        if (value instanceof JSONArray) {
                            sb.append('<');
                            sb.append(key);
                            sb.append('>');
                            sb.append(toXMLString(value));
                            sb.append("</");
                            sb.append(key);
                            sb.append('>');
                        }
                        else {
                            sb.append(toXMLString(value, key));
                        }
                    }
                }
                else if ("".equals(value)) {
                    sb.append('<');
                    sb.append(key);
                    sb.append("/>");

                    // Emit a new tag <k>
                }
                else {
                    sb.append(toXMLString(value, key));
                }
            }
            if (tagName != null) {
                // Emit the </tagname> close tag
                sb.append("</");
                sb.append(tagName);
                sb.append('>');
            }
            return sb.toString();

            // XML does not have good support for arrays. If an array appears in
            // a place
            // where XML is lacking, synthesize an <array> element.

        }
        else {
            if (object instanceof JSONArray) {
                ja = (JSONArray) object;
                length = ja.size();
                for (i = 0; i < length; i += 1) {
                    sb.append(toXMLString(ja.get(i), tagName == null ? "array" : tagName));
                }
                return sb.toString();
            }
            else {
                string = (object == null) ? "null" : escape(object.toString());
                return (tagName == null) ? "\"" + string + "\""
                        : (string.length() == 0) ? "<" + tagName + "/>"
                                : "<" + tagName + ">" + string + "</" + tagName + ">";
            }
        }
    }

    private static JSONObject transferArrayToJSON(JSONArray value_arr, String indexKeyName) {
        JSONObject targetJson = new JSONObject();
        for (int i = 0; i < value_arr.size(); i++) {
            JSONObject json_item = (JSONObject) value_arr.get(i);
            targetJson.put(json_item.getString(indexKeyName), json_item);
        }
        return targetJson;
    }

    public static JSONArray mergerJson(JSONArray target, JSONArray source, String indexKeyName) {
        JSONObject targetJson = transferArrayToJSON(target, indexKeyName);
        JSONArray resultJson = new JSONArray();

        for (int i = 0; i < source.size(); i++) {
            JSONObject source_item = (JSONObject) source.get(i);
            if (targetJson.containsKey(source_item.getString(indexKeyName))) {
                JSONObject target_item = (JSONObject) targetJson.get(source_item.getString(indexKeyName));
                JSONObject merged_Json = merge(target_item, source_item);
                resultJson.add(merged_Json);
            }
        }

        return resultJson;
    }

    public static JSONObject mergerJson(JSONObject targetJsonObj, JSONObject sourceJsonObj, String arrayPath,
            String indexKeyName) {
    	JSONArray target=(JSONArray) JSONPath.eval(targetJsonObj, arrayPath);
    	JSONArray source=(JSONArray) JSONPath.eval(sourceJsonObj, arrayPath);
        setValue(sourceJsonObj, arrayPath, mergerJson(target, source, indexKeyName));
        return sourceJsonObj;
    }
    
	/**
	 * 合併json--遍歷源json的key,把目標json中不存在或節點值爲空的節點進行合併
	 * @param target 目標json 合併到該json中
	 * @param source 源json
	 */
	public static void mergeIfBlank(JSONObject target, JSONObject source){
		Set<String> keys = source.keySet();
		for(String key: keys){
        	String value1 = target.getString(key);
        	String value2 = source.getString(key);
        	if(StringUtils.isBlank(value1) && StringUtils.isNotBlank(value2)){
        		target.put(key, source.get(key));
        	}
        }
	}
	
	public static JSONArray memgerAllArr(JSONArray target, JSONArray source){
		if (source == null) return target;
		int num = target.size();
		for(int i = 0; i < source.size(); i++){
			Object value2 = source.get(i);
			if (i >= num){
	           	 //超出目標數組的索引,直接覆蓋
	           	 target.add(i, value2);
	           	 continue;
            }
			Object value1 = target.get(i);
			
            if(value1 instanceof JSONObject && value2 instanceof JSONObject){
	           	 mergeAll((JSONObject)value1, (JSONObject)value2);
	           	 continue;
            }
            if(value1 instanceof JSONArray && value2 instanceof JSONArray){
            	memgerAllArr((JSONArray)value1, (JSONArray)value2);
           	 	continue;
            }
            //覆蓋
            target.add(i, value2);
		}
		return target;
	}
	
	/**
	 * 合併所有節點,已有節點覆蓋
	 * @param target
	 * @param source
	 * @return
	 */
	public static JSONObject mergeAll(JSONObject target, JSONObject source) {
        if (source == null) return target;

        for(String key : source.keySet()){
        	 Object value1 = target.get(key);
             Object value2 = source.get(key);
             if (value1 == null){
            	 //目標節點爲空直接覆蓋
            	 target.put(key, value2);
            	 continue;
             }
             if(value1 instanceof JSONObject && value2 instanceof JSONObject){
            	 mergeAll((JSONObject)value1, (JSONObject)value2);
            	 continue;
             }
             if(value1 instanceof JSONArray && value2 instanceof JSONArray){
            	 memgerAllArr((JSONArray)value1, (JSONArray)value2);
            	 continue;
             }
             //覆蓋
             target.put(key, value2);
        }
        return target;
    }

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章