This commit is contained in:
Looly
2020-04-07 11:19:46 +08:00
parent cf5ff51a56
commit d8baf83474
11 changed files with 124 additions and 100 deletions

View File

@@ -3,7 +3,7 @@
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------
## 5.2.6 (2020-04-01) ## 5.3.0 (2020-04-07)
### 新特性 ### 新特性
* 【extra 】 JschUtil增加execByShell方法(issue#I1CYES@Gitee) * 【extra 】 JschUtil增加execByShell方法(issue#I1CYES@Gitee)
@@ -25,6 +25,7 @@
* 【extra 】 修复SpringUtil使用devtools重启报错问题 * 【extra 】 修复SpringUtil使用devtools重启报错问题
* 【http 】 修复HttpUtil.encodeParams针对无参数URL问题issue#817@Github * 【http 】 修复HttpUtil.encodeParams针对无参数URL问题issue#817@Github
* 【extra 】 修复模板中无效引用的问题 * 【extra 】 修复模板中无效引用的问题
* 【extra 】 修复读取JSON文本配置未应用到子对象的问题issue#818@Github
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------

View File

@@ -2385,8 +2385,12 @@ public class StrUtil {
} }
/** /**
* 将对象转为字符串<br> * 将对象转为字符串
* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 *
* <pre>
* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组
* 2、对象数组会调用Arrays.toString方法
* <pre/>
* *
* @param obj 对象 * @param obj 对象
* @param charsetName 字符集 * @param charsetName 字符集
@@ -2397,8 +2401,11 @@ public class StrUtil {
} }
/** /**
* 将对象转为字符串<br> * 将对象转为字符串
* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 * <pre>
* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组
* 2、对象数组会调用Arrays.toString方法
* <pre/>
* *
* @param obj 对象 * @param obj 对象
* @param charset 字符集 * @param charset 字符集

View File

@@ -196,7 +196,7 @@ final class InternalJSONUtil {
String segment = path[i]; String segment = path[i];
JSONObject nextTarget = target.getJSONObject(segment); JSONObject nextTarget = target.getJSONObject(segment);
if (nextTarget == null) { if (nextTarget == null) {
nextTarget = new JSONObject(); nextTarget = new JSONObject(target.getConfig());
target.set(segment, nextTarget); target.set(segment, nextTarget);
} }
target = nextTarget; target = nextTarget;

View File

@@ -189,6 +189,11 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
} }
// -------------------------------------------------------------------------------------------------------------------- Constructor start // -------------------------------------------------------------------------------------------------------------------- Constructor start
@Override
public JSONConfig getConfig() {
return this.config;
}
/** /**
* 设置转为字符串时的日期格式默认为时间戳null值 * 设置转为字符串时的日期格式默认为时间戳null值
* *
@@ -295,7 +300,7 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
if (names == null || names.size() == 0 || this.size() == 0) { if (names == null || names.size() == 0 || this.size() == 0) {
return null; return null;
} }
JSONObject jo = new JSONObject(); final JSONObject jo = new JSONObject(this.config);
for (int i = 0; i < names.size(); i += 1) { for (int i = 0; i < names.size(); i += 1) {
jo.set(names.getStr(i), this.getObj(i)); jo.set(names.getStr(i), this.getObj(i));
} }
@@ -591,6 +596,8 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
} else if (source instanceof CharSequence) { } else if (source instanceof CharSequence) {
// JSON字符串 // JSON字符串
init((CharSequence) source); init((CharSequence) source);
}else if (source instanceof JSONTokener) {
init((JSONTokener) source);
} else { } else {
Iterator<?> iter; Iterator<?> iter;
if (source.getClass().isArray()) {// 数组 if (source.getClass().isArray()) {// 数组
@@ -615,7 +622,7 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
*/ */
private void init(CharSequence source) { private void init(CharSequence source) {
if (null != source) { if (null != source) {
init(new JSONTokener(StrUtil.trim(source))); init(new JSONTokener(StrUtil.trim(source), this.config));
} }
} }

View File

@@ -5,12 +5,20 @@ import cn.hutool.core.getter.OptNullBasicTypeFromObjectGetter;
/** /**
* 用于JSON的Getter类提供各种类型的Getter方法 * 用于JSON的Getter类提供各种类型的Getter方法
* @author Looly
* *
* @param <K> Key类型 * @param <K> Key类型
* @author Looly
*/ */
public interface JSONGetter<K> extends OptNullBasicTypeFromObjectGetter<K>{ public interface JSONGetter<K> extends OptNullBasicTypeFromObjectGetter<K> {
/**
* 获取JSON配置
*
* @return {@link JSONConfig}
* @since 5.3.0
*/
JSONConfig getConfig();
/** /**
* key对应值是否为<code>null</code>或无此key * key对应值是否为<code>null</code>或无此key
* *
@@ -20,10 +28,10 @@ public interface JSONGetter<K> extends OptNullBasicTypeFromObjectGetter<K>{
default boolean isNull(K key) { default boolean isNull(K key) {
return JSONNull.NULL.equals(this.getObj(key)); return JSONNull.NULL.equals(this.getObj(key));
} }
/** /**
* 获取字符串类型值,并转义不可见字符,如'\n'换行符会被转义为字符串"\n" * 获取字符串类型值,并转义不可见字符,如'\n'换行符会被转义为字符串"\n"
* *
* @param key 键 * @param key 键
* @return 字符串类型值 * @return 字符串类型值
* @since 4.2.2 * @since 4.2.2
@@ -31,11 +39,11 @@ public interface JSONGetter<K> extends OptNullBasicTypeFromObjectGetter<K>{
default String getStrEscaped(K key) { default String getStrEscaped(K key) {
return getStrEscaped(key, null); return getStrEscaped(key, null);
} }
/** /**
* 获取字符串类型值,并转义不可见字符,如'\n'换行符会被转义为字符串"\n" * 获取字符串类型值,并转义不可见字符,如'\n'换行符会被转义为字符串"\n"
* *
* @param key 键 * @param key
* @param defaultValue 默认值 * @param defaultValue 默认值
* @return 字符串类型值 * @return 字符串类型值
* @since 4.2.2 * @since 4.2.2
@@ -43,51 +51,51 @@ public interface JSONGetter<K> extends OptNullBasicTypeFromObjectGetter<K>{
default String getStrEscaped(K key, String defaultValue) { default String getStrEscaped(K key, String defaultValue) {
return JSONUtil.escape(getStr(key, defaultValue)); return JSONUtil.escape(getStr(key, defaultValue));
} }
/** /**
* 获得JSONArray对象<br> * 获得JSONArray对象<br>
* 如果值为其它类型对象,尝试转换为{@link JSONArray}返回,否则抛出异常 * 如果值为其它类型对象,尝试转换为{@link JSONArray}返回,否则抛出异常
* *
* @param key KEY * @param key KEY
* @return JSONArray对象如果值为null或者非JSONArray类型返回null * @return JSONArray对象如果值为null或者非JSONArray类型返回null
*/ */
default JSONArray getJSONArray(K key) { default JSONArray getJSONArray(K key) {
final Object object = this.getObj(key); final Object object = this.getObj(key);
if(null == object) { if (null == object) {
return null; return null;
} }
if(object instanceof JSONArray) { if (object instanceof JSONArray) {
return (JSONArray) object; return (JSONArray) object;
} }
return new JSONArray(object); return new JSONArray(object, getConfig());
} }
/** /**
* 获得JSONObject对象<br> * 获得JSONObject对象<br>
* 如果值为其它类型对象,尝试转换为{@link JSONObject}返回,否则抛出异常 * 如果值为其它类型对象,尝试转换为{@link JSONObject}返回,否则抛出异常
* *
* @param key KEY * @param key KEY
* @return JSONArray对象如果值为null或者非JSONObject类型返回null * @return JSONArray对象如果值为null或者非JSONObject类型返回null
*/ */
default JSONObject getJSONObject(K key) { default JSONObject getJSONObject(K key) {
final Object object = this.getObj(key); final Object object = this.getObj(key);
if(null == object) { if (null == object) {
return null; return null;
} }
if(object instanceof JSONObject) { if (object instanceof JSONObject) {
return (JSONObject) object; return (JSONObject) object;
} }
return new JSONObject(object); return new JSONObject(object, getConfig());
} }
/** /**
* 从JSON中直接获取Bean对象<br> * 从JSON中直接获取Bean对象<br>
* 先获取JSONObject对象然后转为Bean对象 * 先获取JSONObject对象然后转为Bean对象
* *
* @param <T> Bean类型 * @param <T> Bean类型
* @param key KEY * @param key KEY
* @param beanType Bean类型 * @param beanType Bean类型
* @return Bean对象如果值为null或者非JSONObject类型返回null * @return Bean对象如果值为null或者非JSONObject类型返回null
* @since 3.1.1 * @since 3.1.1
@@ -96,36 +104,36 @@ public interface JSONGetter<K> extends OptNullBasicTypeFromObjectGetter<K>{
final JSONObject obj = getJSONObject(key); final JSONObject obj = getJSONObject(key);
return (null == obj) ? null : obj.toBean(beanType); return (null == obj) ? null : obj.toBean(beanType);
} }
/** /**
* 获取指定类型的对象<br> * 获取指定类型的对象<br>
* 转换失败或抛出异常 * 转换失败或抛出异常
* *
* @param <T> 获取的对象类型 * @param <T> 获取的对象类型
* @param key 键 * @param key
* @param type 获取对象类型 * @param type 获取对象类型
* @return 对象 * @return 对象
* @throws ConvertException 转换异常 * @throws ConvertException 转换异常
* @since 3.0.8 * @since 3.0.8
*/ */
default <T> T get(K key, Class<T> type) throws ConvertException{ default <T> T get(K key, Class<T> type) throws ConvertException {
return get(key, type, false); return get(key, type, false);
} }
/** /**
* 获取指定类型的对象 * 获取指定类型的对象
* *
* @param <T> 获取的对象类型 * @param <T> 获取的对象类型
* @param key 键 * @param key
* @param type 获取对象类型 * @param type 获取对象类型
* @param ignoreError 是否跳过转换失败的对象或值 * @param ignoreError 是否跳过转换失败的对象或值
* @return 对象 * @return 对象
* @throws ConvertException 转换异常 * @throws ConvertException 转换异常
* @since 3.0.8 * @since 3.0.8
*/ */
default <T> T get(K key, Class<T> type, boolean ignoreError) throws ConvertException{ default <T> T get(K key, Class<T> type, boolean ignoreError) throws ConvertException {
final Object value = this.getObj(key); final Object value = this.getObj(key);
if(null == value){ if (null == value) {
return null; return null;
} }
return JSONConverter.jsonConvert(type, value, ignoreError); return JSONConverter.jsonConvert(type, value, ignoreError);

View File

@@ -7,6 +7,7 @@ import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.CaseInsensitiveLinkedMap; import cn.hutool.core.map.CaseInsensitiveLinkedMap;
import cn.hutool.core.map.CaseInsensitiveMap; import cn.hutool.core.map.CaseInsensitiveMap;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.CharUtil; import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
@@ -22,7 +23,6 @@ import java.lang.reflect.Method;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -103,14 +103,17 @@ public class JSONObject implements JSON, JSONGetter<String>, Map<String, Object>
* 构造 * 构造
* *
* @param capacity 初始大小 * @param capacity 初始大小
* @param config JSON配置项 * @param config JSON配置项null表示默认配置
* @since 4.1.19 * @since 4.1.19
*/ */
public JSONObject(int capacity, JSONConfig config) { public JSONObject(int capacity, JSONConfig config) {
if(null == config){
config = JSONConfig.create();
}
if (config.isIgnoreCase()) { if (config.isIgnoreCase()) {
this.rawHashMap = config.isOrder() ? new CaseInsensitiveLinkedMap<>(capacity) : new CaseInsensitiveMap<>(capacity); this.rawHashMap = config.isOrder() ? new CaseInsensitiveLinkedMap<>(capacity) : new CaseInsensitiveMap<>(capacity);
} else { } else {
this.rawHashMap = config.isOrder() ? new LinkedHashMap<>(capacity) : new HashMap<>(capacity); this.rawHashMap = MapUtil.newHashMap(config.isOrder());
} }
this.config = config; this.config = config;
} }
@@ -241,12 +244,7 @@ public class JSONObject implements JSON, JSONGetter<String>, Map<String, Object>
// -------------------------------------------------------------------------------------------------------------------- Constructor end // -------------------------------------------------------------------------------------------------------------------- Constructor end
/** @Override
* 获取JSON配置
*
* @return {@link JSONConfig}
* @since 4.3.1
*/
public JSONConfig getConfig() { public JSONConfig getConfig() {
return this.config; return this.config;
} }
@@ -493,19 +491,16 @@ public class JSONObject implements JSON, JSONGetter<String>, Map<String, Object>
rawHashMap.clear(); rawHashMap.clear();
} }
@SuppressWarnings("NullableProblems")
@Override @Override
public Set<String> keySet() { public Set<String> keySet() {
return this.rawHashMap.keySet(); return this.rawHashMap.keySet();
} }
@SuppressWarnings("NullableProblems")
@Override @Override
public Collection<Object> values() { public Collection<Object> values() {
return rawHashMap.values(); return rawHashMap.values();
} }
@SuppressWarnings("NullableProblems")
@Override @Override
public Set<Entry<String, Object>> entrySet() { public Set<Entry<String, Object>> entrySet() {
return rawHashMap.entrySet(); return rawHashMap.entrySet();
@@ -661,7 +656,7 @@ public class JSONObject implements JSON, JSONGetter<String>, Map<String, Object>
* *
* @param source JavaBean或者Map对象或者String * @param source JavaBean或者Map对象或者String
*/ */
@SuppressWarnings({"rawtypes", "unchecked", "StatementWithEmptyBody"}) @SuppressWarnings({"rawtypes", "unchecked"})
private void init(Object source) { private void init(Object source) {
if (null == source) { if (null == source) {
return; return;
@@ -696,7 +691,7 @@ public class JSONObject implements JSON, JSONGetter<String>, Map<String, Object>
* @param source JSON字符串 * @param source JSON字符串
*/ */
private void init(CharSequence source) { private void init(CharSequence source) {
init(new JSONTokener(StrUtil.trim(source))); init(new JSONTokener(StrUtil.trim(source), this.config));
} }
/** /**
@@ -711,7 +706,7 @@ public class JSONObject implements JSON, JSONGetter<String>, Map<String, Object>
if (x.nextClean() != '{') { if (x.nextClean() != '{') {
throw x.syntaxError("A JSONObject text must begin with '{'"); throw x.syntaxError("A JSONObject text must begin with '{'");
} }
for (;;) { while (true) {
c = x.nextClean(); c = x.nextClean();
switch (c) { switch (c) {
case 0: case 0:

View File

@@ -1,5 +1,7 @@
package cn.hutool.json; package cn.hutool.json;
import cn.hutool.core.util.StrUtil;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@@ -40,14 +42,20 @@ public class JSONTokener {
*/ */
private Reader reader; private Reader reader;
/**
* JSON配置
*/
private JSONConfig config;
// ------------------------------------------------------------------------------------ Constructor start // ------------------------------------------------------------------------------------ Constructor start
/** /**
* 从Reader中构建 * 从Reader中构建
* *
* @param reader Reader * @param reader Reader
* @param config JSON配置
*/ */
public JSONTokener(Reader reader) { public JSONTokener(Reader reader, JSONConfig config) {
this.reader = reader.markSupported() ? reader : new BufferedReader(reader); this.reader = reader.markSupported() ? reader : new BufferedReader(reader);
this.eof = false; this.eof = false;
this.usePrevious = false; this.usePrevious = false;
@@ -61,18 +69,20 @@ public class JSONTokener {
* 从InputStream中构建 * 从InputStream中构建
* *
* @param inputStream InputStream * @param inputStream InputStream
* @param config JSON配置
*/ */
public JSONTokener(InputStream inputStream) throws JSONException { public JSONTokener(InputStream inputStream, JSONConfig config) throws JSONException {
this(new InputStreamReader(inputStream)); this(new InputStreamReader(inputStream), config);
} }
/** /**
* 从字符串中构建 * 从字符串中构建
* *
* @param s JSON字符串 * @param s JSON字符串
* @param config JSON配置
*/ */
public JSONTokener(String s) { public JSONTokener(CharSequence s, JSONConfig config) {
this(new StringReader(s)); this(new StringReader(StrUtil.str(s)), config);
} }
// ------------------------------------------------------------------------------------ Constructor end // ------------------------------------------------------------------------------------ Constructor end
@@ -318,10 +328,10 @@ public class JSONTokener {
return this.nextString(c); return this.nextString(c);
case '{': case '{':
this.back(); this.back();
return new JSONObject(this); return new JSONObject(this, this.config);
case '[': case '[':
this.back(); this.back();
return new JSONArray(this); return new JSONArray(this, this.config);
} }
/* /*
@@ -391,7 +401,7 @@ public class JSONTokener {
* @return {@link JSONArray} * @return {@link JSONArray}
*/ */
public JSONArray toJSONArray() { public JSONArray toJSONArray() {
JSONArray jsonArray = new JSONArray(); JSONArray jsonArray = new JSONArray(this.config);
if (this.nextClean() != '[') { if (this.nextClean() != '[') {
throw this.syntaxError("A JSONArray text must start with '['"); throw this.syntaxError("A JSONArray text must start with '['");
} }

View File

@@ -229,7 +229,7 @@ public class XML {
*/ */
public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException { public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException {
JSONObject jo = new JSONObject(); JSONObject jo = new JSONObject();
XMLTokener x = new XMLTokener(string); XMLTokener x = new XMLTokener(string, jo.getConfig());
while (x.more() && x.skipPast("<")) { while (x.more() && x.skipPast("<")) {
parse(x, jo, null, keepStrings); parse(x, jo, null, keepStrings);
} }

View File

@@ -2,18 +2,19 @@ package cn.hutool.json;
/** /**
* XML分析器继承自JSONTokener提供XML的语法分析 * XML分析器继承自JSONTokener提供XML的语法分析
* *
* @author JSON.org * @author JSON.org
*/ */
public class XMLTokener extends JSONTokener { public class XMLTokener extends JSONTokener {
/** /**
* The table of entity values. It initially contains Character values for amp, apos, gt, lt, quot. * The table of entity values.
* It initially contains Character values for amp, apos, gt, lt, quot.
*/ */
public static final java.util.HashMap<String, Character> entity; public static final java.util.HashMap<String, Character> entity;
static { static {
entity = new java.util.HashMap<String, Character>(8); entity = new java.util.HashMap<>(8);
entity.put("amp", XML.AMP); entity.put("amp", XML.AMP);
entity.put("apos", XML.APOS); entity.put("apos", XML.APOS);
entity.put("gt", XML.GT); entity.put("gt", XML.GT);
@@ -23,16 +24,17 @@ public class XMLTokener extends JSONTokener {
/** /**
* Construct an XMLTokener from a string. * Construct an XMLTokener from a string.
* *
* @param s A source string. * @param s A source string.
* @param config JSON配置
*/ */
public XMLTokener(String s) { public XMLTokener(CharSequence s, JSONConfig config) {
super(s); super(s, config);
} }
/** /**
* Get the text in the CDATA block. * Get the text in the CDATA block.
* *
* @return The string up to the <code>]]&gt;</code>. * @return The string up to the <code>]]&gt;</code>.
* @throws JSONException If the <code>]]&gt;</code> is not found. * @throws JSONException If the <code>]]&gt;</code> is not found.
*/ */
@@ -40,7 +42,7 @@ public class XMLTokener extends JSONTokener {
char c; char c;
int i; int i;
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (;;) { for (; ; ) {
c = next(); c = next();
if (end()) { if (end()) {
throw syntaxError("Unclosed CDATA"); throw syntaxError("Unclosed CDATA");
@@ -55,7 +57,7 @@ public class XMLTokener extends JSONTokener {
} }
/** /**
* Get the next XML outer token, trimming whitespace. * Get the next XML outer token, trimming whitespace.
* There are two kinds of tokens: the '&gt;' character which begins a markup tag, and the content text between markup tags. * There are two kinds of tokens: the '&gt;' character which begins a markup tag, and the content text between markup tags.
* *
* @return A string, or a '&gt;' Character, or null if there is no more source text. * @return A string, or a '&gt;' Character, or null if there is no more source text.
@@ -74,7 +76,7 @@ public class XMLTokener extends JSONTokener {
return XML.LT; return XML.LT;
} }
sb = new StringBuilder(); sb = new StringBuilder();
for (;;) { for (; ; ) {
if (c == '<' || c == 0) { if (c == '<' || c == 0) {
back(); back();
return sb.toString().trim(); return sb.toString().trim();
@@ -90,14 +92,14 @@ public class XMLTokener extends JSONTokener {
/** /**
* Return the next entity. These entities are translated to Characters: <code>&amp; ' &gt; &lt; &quot;</code>. * Return the next entity. These entities are translated to Characters: <code>&amp; ' &gt; &lt; &quot;</code>.
* *
* @param ampersand An ampersand character. * @param ampersand An ampersand character.
* @return A Character or an entity String if the entity is not recognized. * @return A Character or an entity String if the entity is not recognized.
* @throws JSONException If missing ';' in XML entity. * @throws JSONException If missing ';' in XML entity.
*/ */
public Object nextEntity(char ampersand) throws JSONException { public Object nextEntity(char ampersand) throws JSONException {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (;;) { for (; ; ) {
char c = next(); char c = next();
if (Character.isLetterOrDigit(c) || c == '#') { if (Character.isLetterOrDigit(c) || c == '#') {
sb.append(Character.toLowerCase(c)); sb.append(Character.toLowerCase(c));
@@ -114,7 +116,7 @@ public class XMLTokener extends JSONTokener {
/** /**
* Returns the next XML meta token. This is used for skipping over &lt;!...&gt; and &lt;?...?&gt; structures. * Returns the next XML meta token. This is used for skipping over &lt;!...&gt; and &lt;?...?&gt; structures.
* *
* @return Syntax characters (<code>&lt; &gt; / = ! ?</code>) are returned as Character, and strings and names are returned as Boolean. We don't care what the values actually are. * @return Syntax characters (<code>&lt; &gt; / = ! ?</code>) are returned as Character, and strings and names are returned as Boolean. We don't care what the values actually are.
* @throws JSONException 字符串中属性未关闭或XML结构错误抛出此异常。If a string is not properly closed or if the XML is badly structured. * @throws JSONException 字符串中属性未关闭或XML结构错误抛出此异常。If a string is not properly closed or if the XML is badly structured.
*/ */
@@ -142,7 +144,7 @@ public class XMLTokener extends JSONTokener {
case '"': case '"':
case '\'': case '\'':
q = c; q = c;
for (;;) { for (; ; ) {
c = next(); c = next();
if (c == 0) { if (c == 0) {
throw syntaxError("Unterminated string"); throw syntaxError("Unterminated string");
@@ -152,7 +154,7 @@ public class XMLTokener extends JSONTokener {
} }
} }
default: default:
for (;;) { for (; ; ) {
c = next(); c = next();
if (Character.isWhitespace(c)) { if (Character.isWhitespace(c)) {
return Boolean.TRUE; return Boolean.TRUE;
@@ -177,7 +179,7 @@ public class XMLTokener extends JSONTokener {
/** /**
* Get the next XML Token. These tokens are found inside of angle brackets. It may be one of these characters: <code>/ &gt; = ! ?</code> or it may be a string wrapped in single quotes or double * Get the next XML Token. These tokens are found inside of angle brackets. It may be one of these characters: <code>/ &gt; = ! ?</code> or it may be a string wrapped in single quotes or double
* quotes, or it may be a name. * quotes, or it may be a name.
* *
* @return a String or a Character. * @return a String or a Character.
* @throws JSONException If the XML is not well formed. * @throws JSONException If the XML is not well formed.
*/ */
@@ -210,7 +212,7 @@ public class XMLTokener extends JSONTokener {
case '\'': case '\'':
q = c; q = c;
sb = new StringBuilder(); sb = new StringBuilder();
for (;;) { for (; ; ) {
c = next(); c = next();
if (c == 0) { if (c == 0) {
throw syntaxError("Unterminated string"); throw syntaxError("Unterminated string");
@@ -229,7 +231,7 @@ public class XMLTokener extends JSONTokener {
// Name // Name
sb = new StringBuilder(); sb = new StringBuilder();
for (;;) { for (; ; ) {
sb.append(c); sb.append(c);
c = next(); c = next();
if (Character.isWhitespace(c)) { if (Character.isWhitespace(c)) {
@@ -258,7 +260,7 @@ public class XMLTokener extends JSONTokener {
/** /**
* Skip characters until past the requested string. If it is not found, we are left at the end of the source with a result of false. * Skip characters until past the requested string. If it is not found, we are left at the end of the source with a result of false.
* *
* @param to A string to skip past. * @param to A string to skip past.
* @return 是否成功skip * @return 是否成功skip
* @throws JSONException JSON异常 * @throws JSONException JSON异常
@@ -286,7 +288,7 @@ public class XMLTokener extends JSONTokener {
/* We will loop, possibly for all of the remaining characters. */ /* We will loop, possibly for all of the remaining characters. */
for (;;) { for (; ; ) {
j = offset; j = offset;
b = true; b = true;

View File

@@ -189,9 +189,8 @@ public class JSONObjectTest {
public void toBeanTest3() { public void toBeanTest3() {
String jsonStr = "{'data':{'userName':'ak','password': null}}"; String jsonStr = "{'data':{'userName':'ak','password': null}}";
UserWithMap user = JSONUtil.toBean(JSONUtil.parseObj(jsonStr), UserWithMap.class); UserWithMap user = JSONUtil.toBean(JSONUtil.parseObj(jsonStr), UserWithMap.class);
String password = user.getData().get("password"); // Bean默认忽略null
Assert.assertTrue(user.getData().containsKey("password")); Assert.assertFalse(user.getData().containsKey("password"));
Assert.assertNull(password);
} }
@Test @Test

View File

@@ -1,15 +1,10 @@
package cn.hutool.json.test.bean; package cn.hutool.json.test.bean;
import lombok.Data;
import java.util.Map; import java.util.Map;
@Data
public class UserWithMap { public class UserWithMap {
private Map<String, String> data; private Map<String, String> data;
public Map<String, String> getData() {
return data;
}
public void setData(Map<String, String> data) {
this.data = data;
}
} }