com.xiaoleilu.hutool.json.JSONObject Maven / Gradle / Ivy
The newest version!
package com.xiaoleilu.hutool.json;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import com.xiaoleilu.hutool.bean.BeanDesc.PropDesc;
import com.xiaoleilu.hutool.collection.CollectionUtil;
import com.xiaoleilu.hutool.bean.BeanResolver;
import com.xiaoleilu.hutool.bean.BeanUtil;
import com.xiaoleilu.hutool.convert.Convert;
import com.xiaoleilu.hutool.map.CaseInsensitiveLinkedMap;
import com.xiaoleilu.hutool.map.CaseInsensitiveMap;
import com.xiaoleilu.hutool.util.ReflectUtil;
import com.xiaoleilu.hutool.util.StrUtil;
import com.xiaoleilu.hutool.util.TypeUtil;
/**
* JSON对象
* 例:
*
*
* json = new JSONObject().put("JSON", "Hello, World!").toString();
*
*
* @author looly
*/
public class JSONObject extends JSONGetter implements JSON, Map {
/** 默认初始大小 */
private static final int DEFAULT_CAPACITY = 16;
/** JSON的KV持有Map */
private final Map rawHashMap;
/** 是否忽略空值 */
private boolean ignoreNullValue = true;
// -------------------------------------------------------------------------------------------------------------------- Constructor start
/**
* 构造,初始容量为 {@link #DEFAULT_CAPACITY},KEY无序
*/
public JSONObject() {
this(DEFAULT_CAPACITY, false);
}
/**
* 构造,初始容量为 {@link #DEFAULT_CAPACITY}
*
* @param isOrder 是否有序
* @since 3.0.9
*/
public JSONObject(boolean isOrder) {
this(DEFAULT_CAPACITY, isOrder);
}
/**
* 构造
*
* @param capacity 初始大小
* @param isOrder 是否有序
* @since 3.0.9
*/
public JSONObject(int capacity, boolean isOrder) {
this(capacity, false, isOrder);
}
/**
* 构造
*
* @param capacity 初始大小
* @param isIgnoreCase 是否忽略KEY大小写
* @param isOrder 是否有序
* @since 3.3.1
*/
public JSONObject(int capacity, boolean isIgnoreCase, boolean isOrder) {
if (isIgnoreCase) {
this.rawHashMap = isOrder ? new CaseInsensitiveLinkedMap(capacity) : new CaseInsensitiveMap(capacity);
} else {
this.rawHashMap = isOrder ? new LinkedHashMap(capacity) : new HashMap(capacity);
}
}
/**
* 使用其他JSONObject
构造新的JSONObject
,并只加入指定name对应的键值对。
* 此构造方法并不忽略空值
*
* @param jsonObject A JSONObject.
* @param names 需要的name列表
*/
public JSONObject(JSONObject jsonObject, String... names) {
this();
for (String name : names) {
try {
this.putOnce(name, jsonObject.getObj(name));
} catch (Exception ignore) {
}
}
}
/**
* 使用{@link JSONTokener}构建
*
* @param x {@link JSONTokener}
* @throws JSONException 语法错误
*/
public JSONObject(JSONTokener x) throws JSONException {
this();
init(x);
}
/**
* 构建JSONObject,如果给定值为Map,将键值对加入JSON对象;
* 如果为普通的JavaBean,调用其getters方法(getXXX或者isXXX)获得值,加入到JSON对象
* 例如:如果JavaBean对象中有个方法getName(),值为"张三",获得的键值对为:name: "张三"
* 此方法会忽略空值,但是对JSON字符串不影响
*
* @param source JavaBean或者Map对象或者String
*/
public JSONObject(Object source) {
this(source, true);
}
/**
* 构建JSONObject,如果给定值为Map,将键值对加入JSON对象;
* 如果为普通的JavaBean,调用其getters方法(getXXX或者isXXX)获得值,加入到JSON对象
* 例如:如果JavaBean对象中有个方法getName(),值为"张三",获得的键值对为:name: "张三"
*
* @param source JavaBean或者Map对象或者String
* @param ignoreNullValue 是否忽略空值,如果source为JSON字符串,不忽略空值
* @since 3.0.9
*/
public JSONObject(Object source, boolean ignoreNullValue) {
this();
this.ignoreNullValue = ignoreNullValue;
if (null != source) {
if (source instanceof Map) {
for (final Entry, ?> e : ((Map, ?>) source).entrySet()) {
final Object value = e.getValue();
if (false == ignoreNullValue || value != null) {
this.rawHashMap.put(Convert.toStr(e.getKey()), JSONUtil.wrap(value, ignoreNullValue));
}
}
} else if (source instanceof String) {
init((String) source);
} else if (source instanceof Number) {
// ignore Number
} else {
// 普通Bean
this.populateMap(source);
}
}
}
/**
* 使用反射方式获取public字段名和字段值,构建JSONObject对象
* KEY或VALUE任意一个为null则不加入,字段不存在也不加入
*
* @param pojo 包含需要字段的Bean对象
* @param names 需要构建JSONObject的字段名列表
*/
public JSONObject(Object pojo, String[] names) {
this();
Class> c = pojo.getClass();
Field field;
for (String name : names) {
try {
field = c.getField(name);
if (null != field) {
this.putOpt(name, field.get(pojo));
}
} catch (Exception ignore) {
// ignore
}
}
}
/**
* 从JSON字符串解析为JSON对象
*
* @param source 以大括号 {} 包围的字符串,其中KEY和VALUE使用 : 分隔,每个键值对使用逗号分隔
* @exception JSONException JSON字符串语法错误
*/
public JSONObject(String source) throws JSONException {
this(new JSONTokener(source));
}
// -------------------------------------------------------------------------------------------------------------------- Constructor end
/**
* key对应值是否为null
或无此key
*
* @param key 键
* @return true 无此key或值为null
或{@link JSONNull#NULL}返回false
,其它返回true
*/
public boolean isNull(String key) {
return JSONNull.NULL.equals(this.getObj(key));
}
/**
* 将指定KEY列表的值组成新的JSONArray
*
* @param names KEY列表
* @return A JSONArray of values.
* @throws JSONException If any of the values are non-finite numbers.
*/
public JSONArray toJSONArray(Collection names) throws JSONException {
if (CollectionUtil.isEmpty(names)) {
return null;
}
final JSONArray ja = new JSONArray();
Object value;
for (String name : names) {
value = this.get(name);
if (null != value) {
ja.put(value);
}
}
return ja;
}
/**
* 转为实体类对象,转换异常将被抛出
*
* @param Bean类型
* @param clazz 实体类
* @return 实体类对象
*/
public T toBean(Class clazz) {
return toBean(clazz, false);
}
/**
* 转为实体类对象
*
* @param Bean类型
* @param clazz 实体类
* @param ignoreError 是否忽略转换错误
* @return 实体类对象
*/
public T toBean(Class clazz, boolean ignoreError) {
return toBean(ReflectUtil.newInstance(clazz), ignoreError);
}
/**
* 转为实体类对象,转换异常将被抛出
*
* @param Bean类型
* @param type {@link Type}
* @return 实体类对象
* @since 3.0.8
*/
public T toBean(Type type) {
return toBean(type, false);
}
/**
* 转为实体类对象
*
* @param Bean类型
* @param type {@link Type}
* @param ignoreError 是否忽略转换错误
* @return 实体类对象
* @since 3.0.8
*/
@SuppressWarnings("unchecked")
public T toBean(Type type, boolean ignoreError) {
final Class> clazz = TypeUtil.getClass(type);
if (null == clazz) {
throw new IllegalArgumentException(StrUtil.format("Can not know Class of Type {} !", type));
}
return (T) toBean(ReflectUtil.newInstance(clazz), ignoreError);
}
/**
* 转为实体类对象,转换异常将被抛出
*
* @param Bean类型
* @param bean 实体类
* @return 实体类对象
*/
public T toBean(T bean) {
return toBean(bean, false);
}
/**
* 转为实体类对象
*
* @param Bean类型
* @param bean 实体类
* @param ignoreError 是否忽略转换错误
* @return 实体类对象
*/
public T toBean(T bean, boolean ignoreError) {
return InternalJSONUtil.toBean(this, bean, ignoreError);
}
@Override
public int size() {
return rawHashMap.size();
}
@Override
public boolean isEmpty() {
return rawHashMap.isEmpty();
}
@Override
public boolean containsKey(Object key) {
return rawHashMap.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return rawHashMap.containsValue(value);
}
@Override
public Object get(Object key) {
return rawHashMap.get(key);
}
@Override
public Object getObj(String key, Object defaultValue) {
Object obj = this.rawHashMap.get(key);
return null == obj ? defaultValue : obj;
}
@Override
public Object getByExp(String expression) {
return BeanResolver.resolveBean(this, expression);
}
@Override
@SuppressWarnings("unchecked")
public T getByExp(String expression, Class resultType) {
// return Convert.convert(resultType, getByExp(expression));
return (T) InternalJSONUtil.jsonConvert(resultType, getByExp(expression), true);
}
/**
* PUT 键值对到JSONObject中,如果值为null
,将此键移除
*
* @param key 键
* @param value 值对象. 可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL.
* @return this.
* @throws JSONException 值是无穷数字抛出此异常
*/
@Override
public JSONObject put(String key, Object value) throws JSONException {
if (key == null) {
throw new NullPointerException("Null key.");
}
if (value != null) {
InternalJSONUtil.testValidity(value);
this.rawHashMap.put(key, JSONUtil.wrap(value, this.ignoreNullValue));
} else {
this.remove(key);
}
return this;
}
/**
* Put a key/value pair in the JSONObject, but only if the key and the value are both non-null,
* and only if there is not already a member with that name. 一次性Put 键值对,如果key已经存在抛出异常,如果键值中有null值,忽略
*
* @param key 键
* @param value 值对象,可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL.
* @return this.
* @throws JSONException 值是无穷数字、键重复抛出异常
*/
public JSONObject putOnce(String key, Object value) throws JSONException {
if (key != null && value != null) {
if (rawHashMap.containsKey(key)) {
throw new JSONException(StrUtil.format("Duplicate key \"{}\"", key));
}
this.put(key, value);
}
return this;
}
/**
* 在键和值都为非空的情况下put到JSONObject中
*
* @param key 键
* @param value 值对象,可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL.
* @return this.
* @throws JSONException 值是无穷数字
*/
public JSONObject putOpt(String key, Object value) throws JSONException {
if (key != null && value != null) {
this.put(key, value);
}
return this;
}
@Override
public void putAll(Map extends String, ? extends Object> m) {
for (Entry extends String, ? extends Object> entry : m.entrySet()) {
put(entry.getKey(), entry.getValue());
}
}
/**
* 积累值。类似于put,当key对应value已经存在时,与value组成新的JSONArray.
* 如果只有一个值,此值就是value,如果多个值,则是添加到新的JSONArray中
*
* @param key 键
* @param value 被积累的值
* @return this.
* @throws JSONException 如果给定键为null
或者键对应的值存在且为非JSONArray
*/
public JSONObject accumulate(String key, Object value) throws JSONException {
InternalJSONUtil.testValidity(value);
Object object = this.getObj(key);
if (object == null) {
this.put(key, value instanceof JSONArray ? new JSONArray().put(value) : value);
} else if (object instanceof JSONArray) {
((JSONArray) object).put(value);
} else {
this.put(key, new JSONArray().put(object).put(value));
}
return this;
}
/**
* 追加值,如果key无对应值,就添加一个JSONArray,其元素只有value,如果值已经是一个JSONArray,则添加到值JSONArray中。
*
* @param key 键
* @param value 值
* @return this.
* @throws JSONException 如果给定键为null
或者键对应的值存在且为非JSONArray
*/
public JSONObject append(String key, Object value) throws JSONException {
InternalJSONUtil.testValidity(value);
Object object = this.getObj(key);
if (object == null) {
this.put(key, new JSONArray().put(value));
} else if (object instanceof JSONArray) {
this.put(key, ((JSONArray) object).put(value));
} else {
throw new JSONException("JSONObject [" + key + "] is not a JSONArray.");
}
return this;
}
/**
* 对值加一,如果值不存在,赋值1,如果为数字类型,做加一操作
*
* @param key A key string.
* @return this.
* @throws JSONException 如果存在值非Integer, Long, Double, 或 Float.
*/
public JSONObject increment(String key) throws JSONException {
Object value = this.getObj(key);
if (value == null) {
this.put(key, 1);
} else if (value instanceof BigInteger) {
this.put(key, ((BigInteger) value).add(BigInteger.ONE));
} else if (value instanceof BigDecimal) {
this.put(key, ((BigDecimal) value).add(BigDecimal.ONE));
} else if (value instanceof Integer) {
this.put(key, (Integer) value + 1);
} else if (value instanceof Long) {
this.put(key, (Long) value + 1);
} else if (value instanceof Double) {
this.put(key, (Double) value + 1);
} else if (value instanceof Float) {
this.put(key, (Float) value + 1);
} else {
throw new JSONException("Unable to increment [" + JSONUtil.quote(key) + "].");
}
return this;
}
@Override
public Object remove(Object key) {
return rawHashMap.remove(key);
}
@Override
public void clear() {
rawHashMap.clear();
}
@Override
public Set keySet() {
return this.rawHashMap.keySet();
}
@Override
public Collection
© 2015 - 2025 Weber Informatics LLC | Privacy Policy