/* * Copyright 1999-2017 Alibaba Group. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.alibaba.fastjson; import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.parser.Feature; import com.alibaba.fastjson.parser.ParserConfig; import com.alibaba.fastjson.util.TypeUtils; import common.YosException; import common.data.Row; import common.data.Rows; import common.data.db.DBConnect; import java.io.*; import java.lang.reflect.Field; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.math.BigDecimal; import java.math.BigInteger; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import static com.alibaba.fastjson.util.TypeUtils.*; /** * @author wenshao[szujobs@hotmail.com] */ public class JSONObject extends JSON implements Map, Cloneable, Serializable, InvocationHandler { private static final long serialVersionUID = 1L; private static final int DEFAULT_INITIAL_CAPACITY = 16; private final Map map; public JSONObject() { this(DEFAULT_INITIAL_CAPACITY, false); } public JSONObject(Map map) { if (map == null) { throw new IllegalArgumentException("map is null."); } this.map = map; } public JSONObject(boolean ordered) { this(DEFAULT_INITIAL_CAPACITY, ordered); } public JSONObject(int initialCapacity) { this(initialCapacity, false); } public JSONObject(int initialCapacity, boolean ordered) { if (ordered) { map = new LinkedHashMap(initialCapacity); } else { map = new HashMap(initialCapacity); } } public int size() { return map.size(); } public boolean isEmpty() { return map.isEmpty(); } public boolean containsKey(Object key) { return map.containsKey(key); } public boolean containsValue(Object value) { return map.containsValue(value); } public Object get(Object key) { Object val = map.get(key); if (val == null && key instanceof Number) { val = map.get(key.toString()); } return val; } public JSONObject getJSONObject(String key) throws YosException { fieldContainsCheck(key, "JSONObject"); Object value = map.get(key); if (value instanceof JSONObject) { return (JSONObject) value; } if (value instanceof Map) { return new JSONObject((Map) value); } if (value instanceof String) { return JSON.parseObject((String) value); } return (JSONObject) toJSON(value); } public JSONArray getJSONArray(String key) throws YosException { fieldContainsCheck(key, "JSONArray"); Object value = map.get(key); if (value instanceof JSONArray) { return (JSONArray) value; } if (value instanceof List) { return new JSONArray((List) value); } if (value instanceof String) { return (JSONArray) JSON.parse((String) value); } return (JSONArray) toJSON(value); } public T getObject(String key, Class clazz) throws YosException { fieldContainsCheck(key, clazz.getSimpleName()); Object obj = map.get(key); return TypeUtils.castToJavaBean(obj, clazz); } public T getObject(String key, Type type) throws YosException { fieldContainsCheck(key, type.getTypeName()); Object obj = map.get(key); return TypeUtils.cast(obj, type, ParserConfig.getGlobalInstance()); } public T getObject(String key, TypeReference typeReference) throws YosException { fieldContainsCheck(key, typeReference.getType().getTypeName()); Object obj = map.get(key); if (typeReference == null) { return (T) obj; } return TypeUtils.cast(obj, typeReference.getType(), ParserConfig.getGlobalInstance()); } public Boolean getBoolean(String key) throws YosException { fieldContainsCheck(key, "Boolean"); Object value = get(key); if (value == null) { return null; } return castToBoolean(value); } public byte[] getBytes(String key) throws YosException { fieldContainsCheck(key, "Bytes"); Object value = get(key); if (value == null) { return null; } return castToBytes(value); } public boolean getBooleanValue(String key) { Object value = get(key); Boolean booleanVal = castToBoolean(value); if (booleanVal == null) { return false; } return booleanVal.booleanValue(); } public Byte getByte(String key) throws YosException { fieldContainsCheck(key, "Bytes"); Object value = get(key); return castToByte(value); } public byte getByteValue(String key) { Object value = get(key); Byte byteVal = castToByte(value); if (byteVal == null) { return 0; } return byteVal.byteValue(); } public Short getShort(String key) throws YosException { fieldContainsCheck(key, "Short"); Object value = get(key); return castToShort(value); } public short getShortValue(String key) { Object value = get(key); Short shortVal = castToShort(value); if (shortVal == null) { return 0; } return shortVal.shortValue(); } public Integer getInteger(String key) throws YosException { fieldContainsCheck(key, "Integer"); Object value = get(key); return castToInt(value); } public int getIntValue(String key) { Object value = get(key); Integer intVal = castToInt(value); if (intVal == null) { return 0; } return intVal.intValue(); } public int getIntValue(String key, int defaultvalue) { Object value = get(key); Integer intVal = castToInt(value); if (intVal == null) { return defaultvalue; } return intVal.intValue(); } public Long getLong(String key) throws YosException { if (isTableUniqueColumnName(key)) { return getLongValue(key, -1L); } else { fieldContainsCheck(key, "Long"); Object value = get(key); return castToLong(value); } } /** * 检查是否为表id字段 * * @param key * @return */ private static boolean isTableUniqueColumnName(String key) { try { if (tableuniquecolumnnameList.isEmpty()) { tableuniquecolumnnameList = new DBConnect().runSqlQuery("select uniquecolumnname from sys_object").toArrayList("uniquecolumnname"); } return tableuniquecolumnnameList.contains(key); } catch (Exception e) { return false; } } private static ArrayList tableuniquecolumnnameList = new ArrayList<>(); public long getLongValue(String key) { Object value = get(key); Long longVal = castToLong(value); if (longVal == null) { return 0L; } return longVal.longValue(); } public long getLongValue(String key, Long defaultvalue) { Object value = get(key); Long longVal = castToLong(value); if (longVal == null) { return defaultvalue; } return longVal.longValue(); } public Float getFloat(String key) throws YosException { fieldContainsCheck(key, "Float"); Object value = get(key); return castToFloat(value); } public float getFloatValue(String key) { Object value = get(key); Float floatValue = castToFloat(value); if (floatValue == null) { return 0F; } return floatValue.floatValue(); } public Double getDouble(String key) throws YosException { fieldContainsCheck(key, "Double"); Object value = get(key); return castToDouble(value); } public double getDoubleValue(String key) { Object value = get(key); Double doubleValue = castToDouble(value); if (doubleValue == null) { return 0D; } return doubleValue.doubleValue(); } public BigDecimal getBigDecimal(String key) throws YosException { fieldContainsCheck(key, "BigDecimal"); Object value = get(key); return castToBigDecimal(value); } public BigDecimal getBigDecimalValue(String key) throws YosException { Object value = get(key); if (value == null || value.equals("")) { return castToBigDecimal(0); } fieldContainsCheck(key, "BigDecimal"); return castToBigDecimal(value); } public BigDecimal getBigDecimalValue(String key, int defaultvalue) throws YosException { Object value = get(key); if (value == null || value.equals("")) { return castToBigDecimal(defaultvalue); } fieldContainsCheck(key, "BigDecimal"); return castToBigDecimal(value); } public BigInteger getBigInteger(String key) throws YosException { fieldContainsCheck(key, "BigInteger"); Object value = get(key); return castToBigInteger(value); } public String getStringValue(String key) { return getStringValue(key, false); } public String getStringValue(String key, boolean Keepspecialcharacters, String defValue) { Object value = get(key); if (value == null || value.toString().isEmpty()) { return defValue; } if (!Keepspecialcharacters) { value = value.toString().replaceAll("([';])+|(--)+", "");//去除特殊字符,防止sql注入 } else { value = value.toString().replace("'", "\\'"); } return value.toString(); } /** * 验证是否为时间格式 * * @param key * @param pattern * @param defValue * @return */ public String getStringValueForDate(String key, String pattern, String defValue) { Object value = get(key); if (value == null || value.toString().isEmpty()) { return defValue; } SimpleDateFormat sdf = new SimpleDateFormat(pattern); try { sdf.parse(value.toString()); } catch (ParseException e) { e.printStackTrace(); return defValue; } return value.toString(); } public String getStringValue(String key, boolean Keepspecialcharacters) { Object value = get(key); if (value == null) { return ""; } if (!Keepspecialcharacters) { value = value.toString().replaceAll("([';])+|(--)+", "");//去除特殊字符,防止sql注入 } else { value = value.toString().replace("'", "\\'"); } return value.toString(); } public String getString(String key) throws YosException { return getString(key, false); } public String getString(String key, boolean Keepspecialcharacters) throws YosException { fieldContainsCheck(key, "String"); Object value = get(key); if (value == null) { return null; } if (!Keepspecialcharacters) { value = value.toString().replaceAll("([';])+|(--)+", "");//去除特殊字符,防止sql注入 } else { value = value.toString().replace("'", "\\'"); } return value.toString(); } public static HashMap> table_field_length_Map = new HashMap>(); /** * 获取String类型的值,并进行长度校验 * * @param key * @param table_fieldname 数据库表名.字段名 * @return */ public String getString(String key, String table_fieldname) throws YosException { return getString(key, table_fieldname, false); } public String getStringValue(String key, String table_fieldname) throws YosException { Object value = get(key); if (value == null) { return ""; } return getString(key, table_fieldname, false); } /** * 获取String类型的值,并进行长度校验 * * @param key * @param table_fieldname 数据库表名.字段名,如果字段名和key值相同,则可省略字段名 * @return */ public String getString(String key, String table_fieldname, boolean Keepspecialcharacters) throws YosException { String[] split = table_fieldname.toUpperCase().split("[.]"); String tablename = split[0]; if (!table_field_length_Map.containsKey(tablename)) { HashMap map = new HashMap(); DBConnect dbConnect = new DBConnect(); Rows rows = dbConnect.runSqlQuery("select column_name,numeric_precision from sys_objectcols where table_name='" + tablename + "'"); for (Row row : rows) { map.put(row.getString("column_name").toUpperCase(), row.getInteger("numeric_precision")); } table_field_length_Map.put(tablename, map); } String fieldname = split.length == 1 ? key.toUpperCase() : split[1]; int maxlength = table_field_length_Map.get(tablename).getOrDefault(fieldname, 0); return getString(key, maxlength, Keepspecialcharacters); } public String getStringValue(String key, String table_fieldname, boolean Keepspecialcharacters) throws YosException { Object value = get(key); if (value == null) { return ""; } return getString(key, table_fieldname, Keepspecialcharacters); } /** * 获取String类型的值,并进行长度校验 * * @param key * @param maxlength 最大长度限制 * @return */ public String getString(String key, int maxlength) throws YosException { return getString(key, maxlength, false); } public String getStringValue(String key, int maxlength) throws YosException { return getStringValue(key, maxlength, false); } /** * 获取String类型的值,并进行长度校验 * * @param key * @param maxlength 最大长度限制 * @return */ public String getString(String key, int maxlength, boolean Keepspecialcharacters) throws YosException { fieldContainsCheck(key, "String"); String fieldvalue = getString(key); if (fieldvalue != null) { if (maxlength > 0 && fieldvalue.length() > maxlength) { throw new YosException("[" + key + "] 内容超过最大字数" + maxlength + "限制"); } if (!Keepspecialcharacters) { fieldvalue = fieldvalue.replaceAll("([';])+|(--)+", "");//去除特殊字符,防止sql注入 } } return fieldvalue; } /** * 获取String类型的值,并进行长度校验 * * @param key * @param maxlength 最大长度限制 * @return */ public String getStringValue(String key, int maxlength, boolean Keepspecialcharacters) throws YosException { Object value = get(key); if (value == null) { return ""; } return getString(key, maxlength, Keepspecialcharacters); } public Date getDate(String key) throws YosException { fieldContainsCheck(key, "Date"); Object value = get(key); return castToDate(value); } public java.sql.Date getSqlDate(String key) throws YosException { fieldContainsCheck(key, "SqlDate"); Object value = get(key); return castToSqlDate(value); } public java.sql.Timestamp getTimestamp(String key) throws YosException { fieldContainsCheck(key, "Timestamp"); Object value = get(key); return castToTimestamp(value); } public Object put(String key, Object value) { return map.put(key, value); } public JSONObject fluentPut(String key, Object value) { map.put(key, value); return this; } public void putAll(Map m) { map.putAll(m); } public JSONObject fluentPutAll(Map m) { map.putAll(m); return this; } public void clear() { map.clear(); } public JSONObject fluentClear() { map.clear(); return this; } public Object remove(Object key) { return map.remove(key); } public JSONObject fluentRemove(Object key) { map.remove(key); return this; } public Set keySet() { return map.keySet(); } public Collection values() { return map.values(); } public Set> entrySet() { return map.entrySet(); } @Override public Object clone() { return new JSONObject(map instanceof LinkedHashMap // ? new LinkedHashMap(map) // : new HashMap(map) ); } public boolean equals(Object obj) { return this.map.equals(obj); } public int hashCode() { return this.map.hashCode(); } public Object invoke(Object proxy, Method method, Object[] args) { Class[] parameterTypes = method.getParameterTypes(); if (parameterTypes.length == 1) { if (method.getName().equals("equals")) { return this.equals(args[0]); } Class returnType = method.getReturnType(); if (returnType != void.class) { throw new JSONException("illegal setter"); } String name = null; JSONField annotation = TypeUtils.getAnnotation(method, JSONField.class); if (annotation != null) { if (annotation.name().length() != 0) { name = annotation.name(); } } if (name == null) { name = method.getName(); if (!name.startsWith("set")) { throw new JSONException("illegal setter"); } name = name.substring(3); if (name.length() == 0) { throw new JSONException("illegal setter"); } name = Character.toLowerCase(name.charAt(0)) + name.substring(1); } map.put(name, args[0]); return null; } if (parameterTypes.length == 0) { Class returnType = method.getReturnType(); if (returnType == void.class) { throw new JSONException("illegal getter"); } String name = null; JSONField annotation = TypeUtils.getAnnotation(method, JSONField.class); if (annotation != null) { if (annotation.name().length() != 0) { name = annotation.name(); } } if (name == null) { name = method.getName(); if (name.startsWith("get")) { name = name.substring(3); if (name.length() == 0) { throw new JSONException("illegal getter"); } name = Character.toLowerCase(name.charAt(0)) + name.substring(1); } else if (name.startsWith("is")) { name = name.substring(2); if (name.length() == 0) { throw new JSONException("illegal getter"); } name = Character.toLowerCase(name.charAt(0)) + name.substring(1); } else if (name.startsWith("hashCode")) { return this.hashCode(); } else if (name.startsWith("toString")) { return this.toString(); } else { throw new JSONException("illegal getter"); } } Object value = map.get(name); return TypeUtils.cast(value, method.getGenericReturnType(), ParserConfig.getGlobalInstance()); } throw new UnsupportedOperationException(method.toGenericString()); } public Map getInnerMap() { return this.map; } private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException { SecureObjectInputStream.ensureFields(); if (SecureObjectInputStream.fields != null && !SecureObjectInputStream.fields_error) { ObjectInputStream secIn = new SecureObjectInputStream(in); try { secIn.defaultReadObject(); return; } catch (NotActiveException e) { // skip } } in.defaultReadObject(); for (Entry entry : map.entrySet()) { final Object key = entry.getKey(); if (key != null) { ParserConfig.global.checkAutoType(key.getClass()); } final Object value = entry.getValue(); if (value != null) { ParserConfig.global.checkAutoType(value.getClass()); } } } static class SecureObjectInputStream extends ObjectInputStream { static Field[] fields; static volatile boolean fields_error; static void ensureFields() { if (fields == null && !fields_error) { try { final Field[] declaredFields = ObjectInputStream.class.getDeclaredFields(); String[] fieldnames = new String[]{"bin", "passHandle", "handles", "curContext"}; Field[] array = new Field[fieldnames.length]; for (int i = 0; i < fieldnames.length; i++) { Field field = TypeUtils .getField(ObjectInputStream.class , fieldnames[i] , declaredFields ); field.setAccessible(true); array[i] = field; } fields = array; } catch (Throwable error) { fields_error = true; } } } public SecureObjectInputStream(ObjectInputStream in) throws IOException { super(in); try { for (int i = 0; i < fields.length; i++) { final Field field = fields[i]; final Object value = field.get(in); field.set(this, value); } } catch (IllegalAccessException e) { fields_error = true; } } protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { String name = desc.getName(); if (name.length() > 2) { int index = name.lastIndexOf('['); if (index != -1) { name = name.substring(index + 1); } if (name.length() > 2 && name.charAt(0) == 'L' && name.charAt(name.length() - 1) == ';') { name = name.substring(1, name.length() - 1); } ParserConfig.global.checkAutoType(name, null, Feature.SupportAutoType.mask); } return super.resolveClass(desc); } protected Class resolveProxyClass(String[] interfaces) throws IOException, ClassNotFoundException { for (String interfacename : interfaces) { //检查是否处于黑名单 ParserConfig.global.checkAutoType(interfacename, null); } return super.resolveProxyClass(interfaces); } //Hack:默认构造方法会调用这个方法,重写此方法使用反射还原部分关键属性 protected void readStreamHeader() { } } public T toJavaObject(Class clazz) { if (clazz == Map.class || clazz == JSONObject.class || clazz == JSON.class) { return (T) this; } if (clazz == Object.class && !containsKey(JSON.DEFAULT_TYPE_KEY)) { return (T) this; } return TypeUtils.castToJavaBean(this, clazz, ParserConfig.getGlobalInstance()); } public T toJavaObject(Class clazz, ParserConfig config, int features) { if (clazz == Map.class) { return (T) this; } if (clazz == Object.class && !containsKey(JSON.DEFAULT_TYPE_KEY)) { return (T) this; } return TypeUtils.castToJavaBean(this, clazz, config); } /** * 字段栏位是否存在判断 * * @param key * @throws YosException */ public void fieldContainsCheck(String key, String classname) throws YosException { if (!this.containsKey(key)) { throw new YosException(this.getClass().getSimpleName() + "对象中找不到名为" + key + "的" + classname + "类型参数信息"); } } }