Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.xwc1125.common.util.json.JSONObject Maven / Gradle / Ivy
package com.xwc1125.common.util.json;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xwc1125.common.util.string.StringUtils;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @Description: 通用消息对象,基于Map实现的可嵌套数据结构。 支持JSON数据结构。
* @Author: xwc1125
* @Date: 2021/2/23 17:29
* @Copyright Copyright@2021
*/
public class JSONObject extends LinkedHashMap {
private static final long serialVersionUID = 1L;
private static final Pattern arrayNamePattern = Pattern.compile("(\\w+)((\\[\\d+\\])+)");
private static final ObjectMapper objectMapper = new ObjectMapper();
/**
* 数组结构。
*/
public static class JSONArray extends ArrayList {
private static final long serialVersionUID = 1L;
public JSONArray() {
super();
}
public JSONArray(int size) {
super(size);
}
@Override
public String toString() {
try {
return JSON.marshal(this);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public Object set(int index, Object element) {
return super.set(index, transfer(element));
}
@Override
public boolean add(Object element) {
return super.add(transfer(element));
}
@Override
public void add(int index, Object element) {
super.add(index, transfer(element));
}
}
public JSONObject() {
super();
}
public JSONObject(final JSONObject other) {
super(other);
}
@Override
public String toString() {
try {
return JSON.marshal(this);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 转换为紧凑格式的字符串。
*
* @return 返回本对象紧凑格式字符串。
*/
public String toCompactString() {
try {
return objectMapper.writeValueAsString(this);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 获取指定字段的整数值。如果字段不存在,或者无法转换为整数,返回null。
*
* @param name 字段名,支持多级。
* @return 返回指定的整数值,或者null。
*/
public Integer intValue(final String name) {
return valueAsInt(value(name));
}
/**
* 获取指定字段的整数值。如果字段不存在,或者无法转换为整数,返回defaultValue。
*
* @param name 字段名,支持多级。
* @param defaultValue 查询失败时,返回的值。
* @return 返回指定的整数值,或者defaultValue。
*/
public Integer intValue(final String name, final Integer defaultValue) {
return StringUtils.nvl(intValue(name), defaultValue);
}
/**
* 获取指定字段的长整数值。如果字段不存在,或者无法转换为长整数,返回null。
*
* @param name 字段名,支持多级。
* @return 返回指定的长整数值,或者null。
*/
public Long longValue(final String name) {
return valueAsLong(value(name));
}
/**
* 获取指定字段的长整数值。如果字段不存在,或者无法转换为长整数,返回defaultValue。
*
* @param name 字段名,支持多级。
* @param defaultValue 查询失败时,返回的值。
* @return 返回指定的长整数值,或者defaultValue。
*/
public Long longValue(final String name, final Long defaultValue) {
return StringUtils.nvl(longValue(name), defaultValue);
}
/**
* 获取指定字段的布尔值。如果字段不存在,或者无法转换为布尔型,返回null。
*
* @param name 字段名,支持多级。
* @return 返回指定的布尔值,或者null。
*/
public Boolean boolValue(final String name) {
return valueAsBool(value(name));
}
/**
* 获取指定字段的布尔值。如果字段不存在,或者无法转换为布尔型,返回defaultValue。
*
* @param name 字段名,支持多级。
* @param defaultValue 查询失败时,返回的值。
* @return 返回指定的布尔值,或者defaultValue。
*/
public Boolean boolValue(final String name, final Boolean defaultValue) {
return StringUtils.nvl(boolValue(name), defaultValue);
}
/**
* 获取指定字段的字符串值。如果字段不存在,返回null。
*
* @param name 字段名,支持多级。
* @return 返回指定的字符串值,或者null。
*/
public String strValue(final String name) {
return valueAsStr(value(name));
}
/**
* 获取指定字段的字符串值。如果字段不存在,返回defaultValue。
*
* @param name 字段名,支持多级。
* @param defaultValue 查询失败时,返回的值。
* @return 返回指定的字符串值,或者defaultValue。
*/
public String strValue(final String name, final String defaultValue) {
return StringUtils.nvl(strValue(name), defaultValue);
}
/**
* 获取指定字段的值。
*
* @param name 字段名,支持多级,支持数组下标。
* @return 返回指定字段的值。
*/
public Object value(final String name) {
final int indexDot = name.indexOf('.');
if (indexDot >= 0) {
return obj(name.substring(0, indexDot)).value(name.substring(indexDot + 1));
} else {
final Matcher matcher = arrayNamePattern.matcher(name);
if (matcher.find()) {
return endArray(matcher.group(1), matcher.group(2), new EndArrayCallback() {
@Override
public Object callback(JSONArray arr, int index) {
return elementAt(arr, index);
}
});
} else {
return get(name);
}
}
}
/**
* 设置指定字段的值。
*
* @param name 字段名,支持多级,支持数组下标。
* @param value 字段值。
* @return 返回本对象。
*/
public JSONObject value(final String name, final Object value) {
final int indexDot = name.indexOf('.');
if (indexDot >= 0) {
obj(name.substring(0, indexDot)).value(name.substring(indexDot + 1), value);
} else {
final Matcher matcher = arrayNamePattern.matcher(name);
if (matcher.find()) {
endArray(matcher.group(1), matcher.group(2), new EndArrayCallback() {
@Override
public Void callback(JSONArray arr, int index) {
elementAt(arr, index, value);
return null;
}
});
} else {
set(name, value);
}
}
return this;
}
/**
* 获取对象(非标量类型)字段。返回的数据是一个结构体。当不存在指定对象时,则为指定的名字创建一个空的MessageObject对象。
*
* @param name 字段名。不支持多级名字,支持数组下标。
* @return 返回指定的对象。如果对象不存在,则为指定的名字创建一个空的MessageObject对象。
*/
public JSONObject obj(final String name) {
final Matcher matcher = arrayNamePattern.matcher(name);
if (matcher.find()) {
return endArray(matcher.group(1), matcher.group(2), new EndArrayCallback() {
@Override
public JSONObject callback(JSONArray arr, int index) {
return objAt(arr, index);
}
});
} else {
JSONObject obj = getObj(name);
if (obj == null) {
obj = new JSONObject();
put(name, obj);
}
return obj;
}
}
/**
* 获取数组字段。将名字对应的对象以数组对象返回,当指定的字段不存在时,创建一个空的数组。
*
* @param name 字段名。不支持多级名字,不支持下标。
* @return 返回一个数组(List)。
*/
public JSONArray arr(final String name) {
JSONArray arr = getArr(name);
if (arr == null) {
arr = new JSONArray();
put(name, arr);
}
return arr;
}
/**
* 获取对象(非标量类型)字段。返回的数据是一个结构体。
*
* @param name 字段名。
* @return 返回指定的对象字段。
*/
public JSONObject getObj(final String name) {
return (JSONObject) get(name);
}
/**
* 获取数组类型字段。
*
* @param name 字段名。
* @return 返回数组类型字段。
*/
public JSONArray getArr(final String name) {
return (JSONArray) get(name);
}
/**
* 返回字段整数值。如果不存在,返回null。
*
* @param name 字段名。
* @return 返回指定字段整数值。
*/
public Integer getInt(final String name) {
return valueAsInt(get(name));
}
/**
* 返回字段整数值。如果不存在,返回defaultValue。
*
* @param name 字段名。
* @param defaultValue 字段不存在时,返回的值。
* @return 返回指定字段整数值。
*/
public Integer getInt(final String name, Integer defaultValue) {
return StringUtils.nvl(getInt(name), defaultValue);
}
/**
* 返回字段长整数值。如果不存在,返回null。
*
* @param name 字段名。
* @return 返回指定字段长整数值。
*/
public Long getLong(final String name) {
return valueAsLong(get(name));
}
/**
* 返回字段长整数值。如果不存在,返回defaultValue。
*
* @param name 字段名。
* @param defaultValue 字段不存在时,返回的值。
* @return 返回指定字段长整数值。
*/
public Long getLong(final String name, Long defaultValue) {
return StringUtils.nvl(getLong(name), defaultValue);
}
/**
* 返回字段字符串值。如果不存在,返回null。
*
* @param name 字段名。
* @return 返回指定字段字符串值。
*/
public String getStr(final String name) {
return valueAsStr(get(name));
}
/**
* 返回字段字符串值。如果不存在,返回defaultValue。
*
* @param name 字段名。
* @param defaultValue 字段不存在时,返回的值。
* @return 返回指定字段字符串值。
*/
public String getStr(final String name, final String defaultValue) {
return StringUtils.nvl(getStr(name), defaultValue);
}
/**
* 字段值按照布尔类型返回。如果不存在,返回null。
*
* @param name 字段名。
* @return 字段值。
*/
public Boolean getBool(final String name) {
return valueAsBool(get(name));
}
/**
* 字段值按照布尔类型返回。如果不存在,返回defaultValue。
*
* @param name 字段名。
* @param defaultValue 字段不存在时,返回的值。
* @return 字段值。
*/
public Boolean getBool(final String name, final Boolean defaultValue) {
return StringUtils.nvl(getBool(name), defaultValue);
}
/**
* 设置字段值
*
* @param name 字段名
* @param value 字段值(标量:数字、字符串、布尔型;结构体:MessageObject)。 如果是Map类型同时非MessageObject类型,则自动转换为MessageObject类型再存入
* (此时,再修改Map中的数据,将不会体现到本对象中)。
* @return 返回本对象
*/
public JSONObject set(final String name, final Object value) {
put(name, value);
return this;
}
/**
* 将本对象转换为Java Bean。
*
* @param beanClass Java Bean的类对象。
* @return 返回转换后的Java Bean。
*/
public T asBean(Class beanClass) {
try {
return JSON.unmarshal(JSON.marshal(this), beanClass);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 重载基类的方法。如果 value 是 Map 类型,但不是 MessageObject 类型,则创建一个包含内容等同于原 Map 的 MessageObject 作为 value(注意:此后再更改 Map 的内容,将不会反映到
* MessageObject 中)。 重载此方法的目的是为了使JSON能够正确地解析为MessageObject对象。不建议直接调用此方法,请使用 set(name, value)方法设置字段值。
*/
@Override
public Object put(String key, Object value) {
return super.put(key, transfer(value));
}
public static Integer valueAsInt(Object value) {
if (value instanceof Integer) {
return (Integer) value;
} else if (value instanceof Number) {
return ((Number) value).intValue();
} else if (value instanceof String) {
return Integer.valueOf((String) value);
} else if (value instanceof Boolean) {
return ((Boolean) value) ? 1 : 0;
} else {
return null;
}
}
public static Long valueAsLong(Object value) {
if (value instanceof Long) {
return (Long) value;
} else if (value instanceof Number) {
return ((Number) value).longValue();
} else if (value instanceof String) {
return Long.valueOf((String) value);
} else if (value instanceof Boolean) {
return ((Boolean) value) ? 1L : 0L;
} else {
return null;
}
}
public static String valueAsStr(Object value) {
if (value instanceof String) {
return (String) value;
} else if (value != null) {
return value.toString();
} else {
return null;
}
}
public static Boolean valueAsBool(Object value) {
if (value instanceof Boolean) {
return (Boolean) value;
} else if (value instanceof Number) {
return ((Number) value).doubleValue() != 0.0;
} else if (value instanceof String) {
return Boolean.valueOf((String) value);
} else {
return null;
}
}
/**
* 将所有层次中凡是Map类型同时又不是MessageObject的类型,转换为MessageObject类型。
*
* @param value 值。
* @return 返回转换后的值。
*/
@SuppressWarnings("unchecked")
private static Object transfer(final Object value) {
if (!(value instanceof JSONObject) && value instanceof Map) {
return toObj((Map) value);
} else if (!(value instanceof JSONArray) && value instanceof Collection) {
return toArr((Collection) value);
} else {
return value;
}
}
private static JSONArray toArr(final Collection list) {
final JSONArray arr = new JSONArray(list.size());
for (final Object element : list) {
arr.add(element);
}
return arr;
}
private static JSONObject toObj(final Map map) {
final JSONObject obj = new JSONObject();
for (final Map.Entry ent : map.entrySet()) {
obj.put(ent.getKey(), transfer(ent.getValue()));
}
return obj;
}
/**
* 将指定下标元素作为数组返回,如果不存在,则在该位置创建一个空的数组。
*
* @param arr 当前数组。
* @param index 下标。
* @return 返回当前数组指定下标的元素,该元素应该是一个数组。
*/
private static JSONArray arrayAt(JSONArray arr, int index) {
expand(arr, index);
if (arr.get(index) == null) {
arr.set(index, new JSONArray());
}
return (JSONArray) arr.get(index);
}
/**
* 将指定下标元素作为结构体返回,如果不存在,则在该位置创建一个空的结构体。
*
* @param arr 当前数组。
* @param index 下标。
* @return 返回当前数组指定下标元素,该元素是一个结构体。
*/
private static JSONObject objAt(final JSONArray arr, int index) {
expand(arr, index);
if (arr.get(index) == null) {
arr.set(index, new JSONObject());
}
return (JSONObject) arr.get(index);
}
/**
* 设置数组指定下标位置的值。
*
* @param arr 数组。
* @param index 下标。
* @param value 值。
*/
private static void elementAt(final JSONArray arr, final int index, final Object value) {
expand(arr, index).set(index, value);
}
/**
* 获取数组指定下标元素的值。
*
* @param arr 数组。
* @param index 下标。
* @return 值。
*/
private static Object elementAt(final JSONArray arr, final int index) {
return expand(arr, index).get(index);
}
/**
* 扩展数组到指定下标,以防止访问时下标越界。
*
* @param arr 数组
* @param index 下标
* @return 返回传入的数组
*/
private static JSONArray expand(final JSONArray arr, final int index) {
while (arr.size() <= index) {
arr.add(null);
}
return arr;
}
/**
* 最后数组回调。
*
* @param 回调返回数据类型。
* @author Mike
*/
private interface EndArrayCallback {
/**
* 当定位到最后一级数组,将调用本方法。
*
* @param arr 最后一级数组对象。
* @param index 最后一级索引。
* @return 返回回调的返回值。
*/
T callback(JSONArray arr, int index);
}
/**
* 处理多维数组的工具函数(包括一维数组)。多维数组的名字如:arrary[1][2][3], 则name=array,indexStr=[1][2][3],在callback中,endArr将是
* array[1][2]指定的对象,indexe=3。
*
* @param name 不带下标的名字,不支持多级名字。
* @param indexesStr 索引部分的字符串,如:[1][2][3]
* @param callback 回调函数。
* @return 返回回调函数的返回值。
*/
private T endArray(final String name, final String indexesStr, final EndArrayCallback callback) {
JSONArray endArr = arr(name);
final int[] indexes = parseIndexes(indexesStr);
int i = 0;
while (i < indexes.length - 1) {
endArr = arrayAt(endArr, indexes[i++]);
}
return callback.callback(endArr, indexes[i]);
}
private static int[] parseIndexes(final String s) {
int[] indexes = null;
List list = new ArrayList();
final StringTokenizer st = new StringTokenizer(s, "[]");
while (st.hasMoreTokens()) {
final int index = Integer.valueOf(st.nextToken());
if (index < 0) {
throw new RuntimeException(String.format("Illegal index %1$d in \"%2$s\"", index, s));
}
list.add(index);
}
indexes = new int[list.size()];
int i = 0;
for (Integer tmp : list.toArray(new Integer[list.size()])) {
indexes[i++] = tmp;
}
return indexes;
}
}