public Class<?>[] extract(Mirror<?> mirror) { Class<?> theType = mirror.getType(); List<Class<?>> re = new ArrayList<Class<?>>(5); // 原生类型,增加其外覆类 if (theType.isPrimitive()) { re.add(mirror.getWrapperClass()); // 数字 if (theType != boolean.class && theType != char.class) { re.add(Number.class); } } // 日历 else if (mirror.isOf(Calendar.class)) { re.add(Calendar.class); } // 其他类型,直接增加,并试图判断其抽象类 else { re.add(theType); // 枚举 if (mirror.klass.isEnum()) { re.add(Enum.class); } // 数组 else if (mirror.klass.isArray()) { re.add(Array.class); } // 字符串 else if (mirror.isStringLike()) re.add(CharSequence.class); // 数字 else if (mirror.isNumber()) { re.add(Number.class); } // Map else if (mirror.isOf(Map.class)) { re.add(Map.class); } // 列表 else if (mirror.isOf(List.class)) { re.add(List.class); re.add(Collection.class); } // 集合 else if (mirror.isOf(Collection.class)) { re.add(Collection.class); } } // 最后确保 Object 一定被加上了 if (theType != Object.class) re.add(Object.class); return re.toArray(new Class<?>[re.size()]); }
@SuppressWarnings("unchecked") private static <T extends Map<String, Object>> void obj2map( Object obj, T map, Map<Object, Object> memo) { if (null == obj || memo.containsKey(obj)) return; memo.put(obj, ""); Mirror<?> mirror = Mirror.me(obj.getClass()); Field[] flds = mirror.getFields(); for (Field fld : flds) { Object v = mirror.getValue(obj, fld); if (null == v) { map.put(fld.getName(), null); continue; } Mirror<?> mr = Mirror.me(fld.getType()); if (mr.isNumber() || mr.isBoolean() || mr.isChar() || mr.isStringLike() || mr.isEnum() || mr.isDateTimeLike()) { map.put(fld.getName(), v); } else if (memo.containsKey(v)) { map.put(fld.getName(), null); } else { T sub; try { sub = (T) map.getClass().newInstance(); } catch (Exception e) { throw Lang.wrapThrow(e); } obj2map(v, sub, memo); map.put(fld.getName(), sub); } } }
/** * 判断两个对象是否相等。 这个函数用处是: * * <ul> * <li>可以容忍 null * <li>可以容忍不同类型的 Number * <li>对数组,集合, Map 会深层比较 * </ul> * * 当然,如果你重写的 equals 方法会优先 * * @param a1 比较对象1 * @param a2 比较对象2 * @return 是否相等 */ @SuppressWarnings("unchecked") public static boolean equals(Object a1, Object a2) { if (a1 == a2) return true; if (a1 == null && a2 == null) return false; if (a1 == null || a2 == null) return false; if (a1.equals(a2)) return true; Mirror<?> mr1 = Mirror.me(a1); if (mr1.isStringLike()) { return a1.toString().equals(a2.toString()); } if (mr1.isDateTimeLike()) { return a1.equals(a2); } if (mr1.isNumber()) { return a2 instanceof Number && a1.toString().equals(a2.toString()); } if (!a1.getClass().isAssignableFrom(a2.getClass()) && !a2.getClass().isAssignableFrom(a1.getClass())) return false; if (a1 instanceof Map && a2 instanceof Map) { Map<?, ?> m1 = (Map<?, ?>) a1; Map<?, ?> m2 = (Map<?, ?>) a2; if (m1.size() != m2.size()) return false; for (Entry<?, ?> e : m1.entrySet()) { Object key = e.getKey(); if (!m2.containsKey(key) || !equals(m1.get(key), m2.get(key))) return false; } return true; } else if (a1.getClass().isArray()) { if (a2.getClass().isArray()) { int len = Array.getLength(a1); if (len != Array.getLength(a2)) return false; for (int i = 0; i < len; i++) { if (!equals(Array.get(a1, i), Array.get(a2, i))) return false; } return true; } else if (a2 instanceof List) { return equals(a1, Lang.collection2array((List<Object>) a2, Object.class)); } return false; } else if (a1 instanceof List) { if (a2 instanceof List) { List<?> l1 = (List<?>) a1; List<?> l2 = (List<?>) a2; if (l1.size() != l2.size()) return false; int i = 0; for (Iterator<?> it = l1.iterator(); it.hasNext(); ) { if (!equals(it.next(), l2.get(i++))) return false; } return true; } else if (a2.getClass().isArray()) { return equals(Lang.collection2array((List<Object>) a1, Object.class), a2); } return false; } else if (a1 instanceof Collection && a2 instanceof Collection) { Collection<?> c1 = (Collection<?>) a1; Collection<?> c2 = (Collection<?>) a2; if (c1.size() != c2.size()) return false; return c1.containsAll(c2) && c2.containsAll(c1); } return false; }
public void render(Object obj) throws IOException { if (null == obj) { writer.write("null"); } else if (obj instanceof JsonRender) { ((JsonRender) obj).render(null); } else if (obj instanceof Class) { string2Json(((Class<?>) obj).getName()); } else if (obj instanceof Mirror) { string2Json(((Mirror<?>) obj).getType().getName()); } else { Mirror mr = Mirror.me(obj.getClass()); // 枚举 if (mr.isEnum()) { string2Json(((Enum) obj).name()); } // 数字,布尔等 else if (mr.isNumber()) { String tmp = obj.toString(); if (tmp.equals("NaN")) { // TODO 怎样才能应用上JsonFormat中是否忽略控制呢? // 因为此时已经写入了key: writer.write("null"); } else writer.write(tmp); } else if (mr.isBoolean()) { writer.append(obj.toString()); } // 字符串 else if (mr.isStringLike() || mr.isChar()) { string2Json(obj.toString()); } // 日期时间 else if (mr.isDateTimeLike()) { boolean flag = true; if (obj instanceof Date) { DateFormat df = format.getDateFormat(); if (df != null) { string2Json(df.format((Date) obj)); flag = false; } } if (flag) string2Json(format.getCastors().castToString(obj)); } // 其他 else { // Map if (obj instanceof Map) { map2Json((Map) obj); } // 集合 else if (obj instanceof Collection) { coll2Json((Collection) obj); } // 数组 else if (obj.getClass().isArray()) { array2Json(obj); } // 普通 Java 对象 else { memo.add(obj); pojo2Json(obj); memo.remove(obj); } } } }