注意:仅供学习用,切勿用于生产
package com.servlet.demo.framework.utill;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.text.SimpleDateFormat;
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.Stack;
import com.servlet.demo.framework.utill.clazz.ClassUtil;
/**
* json简单工具类
* 支持对象>JSON ; JSON > 对象
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public class JsonUtil {
private static int convertDepth = 15;
private static String timestampPattern = "yyyy-MM-dd HH:mm:ss";
private static String datePattern = "yyyy-MM-dd";
public static void setConvertDepth(int convertDepth) {
if (convertDepth < 2) throw new IllegalArgumentException("convert depth can not less than 2.");
JsonUtil.convertDepth = convertDepth;
}
public static void setTimestampPattern(String timestampPattern) {
if (timestampPattern == null || "".equals(timestampPattern.trim())) throw new IllegalArgumentException("timestampPattern can not be blank.");
JsonUtil.timestampPattern = timestampPattern;
}
public static void setDatePattern(String datePattern) {
if (datePattern == null || "".equals(datePattern.trim())) throw new IllegalArgumentException("datePattern can not be blank.");
JsonUtil.datePattern = datePattern;
}
// ===================================================================================
public static String toJson(Object value) {
return toJson(value, convertDepth);
}
public static String toJson(Object value, int depth) {
if (value == null || (depth--) < 0) return "null";
if (value instanceof String) return "\"" + escape((String) value) + "\"";
if (value instanceof Double) {
if (((Double) value).isInfinite() || ((Double) value).isNaN())
return "null";
else
return value.toString();
}
if (value instanceof Float) {
if (((Float) value).isInfinite() || ((Float) value).isNaN())
return "null";
else
return value.toString();
}
if (value instanceof Number) return value.toString();
if (value instanceof Boolean) return value.toString();
if (value instanceof java.util.Date) {
if (value instanceof java.sql.Timestamp) return "\"" + new SimpleDateFormat(timestampPattern).format(value) + "\"";
if (value instanceof java.sql.Time) return "\"" + value.toString() + "\"";
return "\"" + new SimpleDateFormat(datePattern).format(value) + "\"";
}
if (value instanceof Map) {
return mapToJson((Map) value, depth);
}
if (value instanceof List) {
return listToJson((List) value, depth);
}
String result = otherToJson(value, depth);
if (result != null) return result;
// 类型无法处理时当作字符串处理,否则ajax调用返回时js无法解析
// return value.toString();
return "\"" + escape(value.toString()) + "\"";
}
private static String mapToJson(Map map, int depth) {
if (map == null) return "null";
StringBuilder sb = new StringBuilder();
boolean first = true;
Iterator iter = map.entrySet().iterator();
sb.append('{');
while (iter.hasNext()) {
if (first)
first = false;
else
sb.append(',');
Map.Entry entry = (Map.Entry) iter.next();
toKeyValue(String.valueOf(entry.getKey()), entry.getValue(), sb, depth);
}
sb.append('}');
return sb.toString();
}
private static String toKeyValue(String key, Object value, StringBuilder sb, int depth) {
sb.append('\"');
if (key == null)
sb.append("null");
else
escape(key, sb);
sb.append('\"').append(':');
sb.append(toJson(value, depth));
return sb.toString();
}
private static String listToJson(List list, int depth) {
if (list == null) return "null";
boolean first = true;
StringBuilder sb = new StringBuilder();
Iterator iter = list.iterator();
sb.append('[');
while (iter.hasNext()) {
if (first)
first = false;
else
sb.append(',');
Object value = iter.next();
if (value == null) {
sb.append("null");
continue;
}
sb.append(toJson(value, depth));
}
sb.append(']');
return sb.toString();
}
/**
* Escape quotes, \, /, \r, \n, \b, \f, \t and other control characters
* (U+0000 through U+001F).
*/
private static String escape(String s) {
if (s == null) return null;
StringBuilder sb = new StringBuilder();
escape(s, sb);
return sb.toString();
}
private static void escape(String s, StringBuilder sb) {
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
switch (ch) {
case '"':
sb.append("\\\"");
break;
case '\\':
sb.append("\\\\");
break;
case '\b':
sb.append("\\b");
break;
case '\f':
sb.append("\\f");
break;
case '\n':
sb.append("\\n");
break;
case '\r':
sb.append("\\r");
break;
case '\t':
sb.append("\\t");
break;
// case '/':
// sb.append("\\/");
// break;
default:
if ((ch >= '\u0000' && ch <= '\u001F') || (ch >= '\u007F' && ch <= '\u009F') || (ch >= '\u2000' && ch <= '\u20FF')) {
String str = Integer.toHexString(ch);
sb.append("\\u");
for (int k = 0; k < 4 - str.length(); k++) {
sb.append('0');
}
sb.append(str.toUpperCase());
} else {
sb.append(ch);
}
}
}
}
private static String otherToJson(Object value, int depth) {
if (value instanceof Character) {
return "\"" + escape(value.toString()) + "\"";
}
if (value instanceof Object[]) {
Object[] arr = (Object[]) value;
List list = new ArrayList(arr.length);
for (int i = 0; i < arr.length; i++)
list.add(arr[i]);
return listToJson(list, depth);
}
if (value instanceof Enum) {
return "\"" + ((Enum) value).toString() + "\"";
}
if (value instanceof Class) {
return "\"" + ((Class) value).getName() + "\"";
}
return beanToJson(value, depth);
}
private static String beanToJson(Object model, int depth) {
Map map = new HashMap();
Method[] methods = model.getClass().getMethods();
for (Method m : methods) {
String methodName = m.getName();
int indexOfGet = methodName.indexOf("get");
if (indexOfGet == 0 && methodName.length() > 3) { // Only getter
String attrName = methodName.substring(3);
if (!attrName.equals("Class")) { // Ignore Object.getClass()
Class<?>[] types = m.getParameterTypes();
if (types.length == 0) {
try {
Object value = m.invoke(model);
map.put(FormatUtil.firstCharToLowerCase(attrName), value);
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
}
} else {
int indexOfIs = methodName.indexOf("is");
if (indexOfIs == 0 && methodName.length() > 2) {
String attrName = methodName.substring(2);
Class<?>[] types = m.getParameterTypes();
if (types.length == 0) {
try {
Object value = m.invoke(model);
map.put(FormatUtil.firstCharToLowerCase(attrName), value);
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
}
}
}
return mapToJson(map, depth);
}
// ========================================================
public static Object parse(String jsonStr) {
int len = jsonStr.length();
String sp = "|";//
Boolean cs = Boolean.FALSE, ignore = Boolean.FALSE;
Stack<Character> s1 = new Stack<Character>();// 符号
Stack<Object> s2 = new Stack<Object>();// 值
StringBuffer sb = new StringBuffer();
for (int i = 0; i < len; i++) {
char c = jsonStr.charAt(i);
switch (c) {
case '{':
case '[':
s1.add(c);
s2.add(sp);
sb.setLength(0);
break;
case ']':
case '}':
if (s1.peek() != '"') {
cs = addCheck(sb, cs, s2);
char ls2 = s1.pop();
if ((c == '}' && ls2 != '{') || (c == ']' && ls2 != '[')) throw new RuntimeException("JSON 格式错误 ");
Object obj = null;
// =================
if (c == '}') {// map
Map map = new HashMap<>();
while (!sp.equals(s2.peek())) {
Object v = s2.pop();
if ("".equals(v) && sp.equals(s2.peek())) // 验证空对象
continue;
Object k = s2.pop();
map.put(k, v);
}
obj = map;
}
if (c == ']') {// list
List list = new ArrayList<>();
while (!sp.equals(s2.peek())) {
list.add(s2.pop());
}
obj = list;
}
// =================
s2.pop();
s2.add(obj);
ignore = Boolean.TRUE;
} else {
sb.append(c);
}
break;
case '"':
if (jsonStr.charAt(i - 1) != '\\') if (s1.peek() == '"') {
s1.pop();
cs = Boolean.TRUE;
} else
s1.add('"');
break;
case ':':
case ',':
if (s1.peek() != '"') {
if (ignore && c == ',') {
ignore = Boolean.FALSE;
continue;
}
cs = addCheck(sb, cs, s2);
} else {
sb.append(c);
}
break;
default:
sb.append(c);
break;
}
}
if (!s1.isEmpty()) System.out.println("JSON 格式结尾缺失");
return s2.pop();
}
private static boolean addCheck(StringBuffer sb, Boolean cs, Stack<Object> s2) {
Object val = sb.toString().trim();
if (!cs) {
if (FormatUtil.isNumber(val))
val = FormatUtil.toLong(val);
else if (FormatUtil.isDecimal(val))
val = FormatUtil.toDouble(val);
else if (((String) val).equalsIgnoreCase("null"))
val = null;
else if (((String) val).equalsIgnoreCase("")) {
sb.setLength(0);
return false;
} else
val = FormatUtil.toBoolean(val);
}
s2.add(val);
sb.setLength(0);
return false;
}
public static <T> Object parse(String jsonStr, Class<T> clazz) throws Exception {
Object jsonObj = parse(jsonStr);
return parseBean(jsonObj, clazz);
}
private static <T> Object parseBean(Object json, Class<T> clazz) throws Exception {
try {
if (json instanceof List) {
List<T> list = new ArrayList<T>();
for (Object obj : (List) json) {
if (!obj.equals("")) {
list.add((T) parseBean(obj, clazz));
}
}
return list;
} else if (json instanceof Map) {
Object obj = null;
obj = clazz.newInstance();
Set<Map.Entry<?, ?>> setMap = ((Map) json).entrySet();
for (Map.Entry<?, ?> en : setMap) {
String key = FormatUtil.toString(en.getKey());
Object value = en.getValue();
Method m = null;
for (Method mt : clazz.getMethods()) {
if (mt.getName().equals("set" + FormatUtil.firstCharToUpperCase(key))) m = mt;
}
if (m != null) {
Class cla = m.getParameterTypes()[0];
Object args = null;
if (value != null) {
if (cla.isAssignableFrom(Map.class)) {
cla = (Class) ((ParameterizedType) (m.getGenericParameterTypes()[0])).getActualTypeArguments()[1];
Map map = new HashMap<>();
Set<Map.Entry<?, ?>> setMap2 = ((Map) value).entrySet();
for (Map.Entry<?, ?> en2 : setMap2) {
map.put(parseBean(en2.getKey(), String.class), parseBean(en2.getValue(), cla));
}
args = map;
} else {
if (cla.isAssignableFrom(List.class)) cla = (Class) ((ParameterizedType) (m.getGenericParameterTypes()[0])).getActualTypeArguments()[0];
args = parseBean(value, cla);
}
}
m.invoke(obj, args);
}
}
return obj;
} else if (json instanceof String[]) {
String[] strs = (String[]) json;
Object[] objs = new Object[strs.length];
for (int i = 0; i < strs.length; i++) {
objs[i] = parse(strs[i], clazz);
}
return objs;
} else {
if (ClassUtil.isString(clazz)) {
return FormatUtil.toString(json);
} else if (ClassUtil.isDouble(clazz)) {
return FormatUtil.toDouble(json);
} else if (ClassUtil.isInt(clazz)) {
return FormatUtil.toInt(json);
} else if (ClassUtil.isLong(clazz)) {
return FormatUtil.toLong(json);
} else if (ClassUtil.isDecimal(clazz)) {
return FormatUtil.toDecimal(json);
} else if (ClassUtil.isBool(clazz)) {
return FormatUtil.toBoolean(json);
} else {
throw new Exception("未知文件类型转换:value=" + json + ",type=" + clazz);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}