This commit is contained in:
Looly 2022-06-23 11:41:55 +08:00
parent 26079dbb29
commit 4417e5cd00
23 changed files with 547 additions and 458 deletions

View File

@ -69,6 +69,7 @@ import java.util.concurrent.atomic.AtomicReference;
* @since 6.0.0 * @since 6.0.0
*/ */
public class RegisterConverter implements Converter, Serializable { public class RegisterConverter implements Converter, Serializable {
private static final long serialVersionUID = 1L;
/** /**
* 默认类型转换器 * 默认类型转换器

View File

@ -17,7 +17,7 @@ public class RestTest {
@Test @Test
public void contentTypeTest() { public void contentTypeTest() {
final HttpRequest request = HttpRequest.post("http://localhost:8090/rest/restTest/")// final HttpRequest request = HttpRequest.post("http://localhost:8090/rest/restTest/")//
.body(JSONUtil.createObj() .body(JSONUtil.ofObj()
.set("aaa", "aaaValue") .set("aaa", "aaaValue")
.set("键2", "值2").toString()); .set("键2", "值2").toString());
Assert.assertEquals("application/json;charset=UTF-8", request.header("Content-Type")); Assert.assertEquals("application/json;charset=UTF-8", request.header("Content-Type"));
@ -27,7 +27,7 @@ public class RestTest {
@Ignore @Ignore
public void postTest() { public void postTest() {
final HttpRequest request = HttpRequest.post("http://localhost:8090/rest/restTest/")// final HttpRequest request = HttpRequest.post("http://localhost:8090/rest/restTest/")//
.body(JSONUtil.createObj() .body(JSONUtil.ofObj()
.set("aaa", "aaaValue") .set("aaa", "aaaValue")
.set("键2", "值2").toString()); .set("键2", "值2").toString());
Console.log(request.execute().body()); Console.log(request.execute().body());
@ -36,7 +36,7 @@ public class RestTest {
@Test @Test
@Ignore @Ignore
public void postTest2() { public void postTest2() {
final String result = HttpUtil.post("http://localhost:8090/rest/restTest/", JSONUtil.createObj()// final String result = HttpUtil.post("http://localhost:8090/rest/restTest/", JSONUtil.ofObj()//
.set("aaa", "aaaValue") .set("aaa", "aaaValue")
.set("键2", "值2").toString()); .set("键2", "值2").toString());
Console.log(result); Console.log(result);
@ -47,7 +47,7 @@ public class RestTest {
public void getWithBodyTest() { public void getWithBodyTest() {
final HttpRequest request = HttpRequest.get("http://localhost:8888/restTest")// final HttpRequest request = HttpRequest.get("http://localhost:8888/restTest")//
.header(Header.CONTENT_TYPE, "application/json") .header(Header.CONTENT_TYPE, "application/json")
.body(JSONUtil.createObj() .body(JSONUtil.ofObj()
.set("aaa", "aaaValue") .set("aaa", "aaaValue")
.set("键2", "值2").toString()); .set("键2", "值2").toString());
Console.log(request.execute().body()); Console.log(request.execute().body());
@ -60,7 +60,7 @@ public class RestTest {
// Charles代理 // Charles代理
.setHttpProxy("localhost", 8888) .setHttpProxy("localhost", 8888)
.header("Access-Token","") .header("Access-Token","")
.body(JSONUtil.createObj() .body(JSONUtil.ofObj()
.set("advertiser_ids", new Long[] {1690657248243790L}) .set("advertiser_ids", new Long[] {1690657248243790L})
.set("fields", new String[] {"id", "name", "status"}).toString()); .set("fields", new String[] {"id", "name", "status"}).toString());
Console.log(request); Console.log(request);

View File

@ -27,7 +27,7 @@ public class SimpleServerTest {
) )
// 返回JSON数据测试 // 返回JSON数据测试
.addAction("/restTest", (request, response) -> { .addAction("/restTest", (request, response) -> {
final String res = JSONUtil.createObj() final String res = JSONUtil.ofObj()
.set("id", 1) .set("id", 1)
.set("method", request.getMethod()) .set("method", request.getMethod())
.set("request", request.getBody()) .set("request", request.getBody())

View File

@ -1,7 +1,9 @@
package cn.hutool.json; package cn.hutool.json;
import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.codec.HexUtil;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.lang.mutable.MutableEntry; import cn.hutool.core.lang.mutable.MutableEntry;
import cn.hutool.core.map.CaseInsensitiveLinkedMap; import cn.hutool.core.map.CaseInsensitiveLinkedMap;
import cn.hutool.core.map.CaseInsensitiveTreeMap; import cn.hutool.core.map.CaseInsensitiveTreeMap;
@ -11,9 +13,12 @@ import cn.hutool.core.text.StrUtil;
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.ObjUtil; import cn.hutool.core.util.ObjUtil;
import cn.hutool.json.convert.JSONConverter; import cn.hutool.json.convert.JSONConverterOld;
import cn.hutool.json.serialize.JSONString; import cn.hutool.json.serialize.JSONString;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.sql.SQLException; import java.sql.SQLException;
import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalAccessor;
@ -144,7 +149,7 @@ public final class InternalJSONUtil {
} else if (ArrayUtil.isArray(value)) { } else if (ArrayUtil.isArray(value)) {
return new JSONArray(value).toString(); return new JSONArray(value).toString();
} else { } else {
return JSONUtil.quote(value.toString()); return quote(value.toString());
} }
} }
@ -255,7 +260,88 @@ public final class InternalJSONUtil {
.setTransientSupport(config.isTransientSupport()) .setTransientSupport(config.isTransientSupport())
// 使用JSON转换器 // 使用JSON转换器
.setConverter((type, value) -> .setConverter((type, value) ->
JSONConverter.convertWithCheck(type, value, null, config.isIgnoreError())); JSONConverterOld.convertWithCheck(type, value, null, config.isIgnoreError()));
}
/**
* 对所有双引号做转义处理使用双反斜杠做转义<br>
* 为了能在HTML中较好的显示会将&lt;/转义为&lt;\/<br>
* JSON字符串中不能包含控制字符和未经转义的引号和反斜杠
*
* @param string 字符串
* @return 适合在JSON中显示的字符串
*/
public static String quote(final String string) {
return quote(string, true);
}
/**
* 对所有双引号做转义处理使用双反斜杠做转义<br>
* 为了能在HTML中较好的显示会将&lt;/转义为&lt;\/<br>
* JSON字符串中不能包含控制字符和未经转义的引号和反斜杠
*
* @param string 字符串
* @param isWrap 是否使用双引号包装字符串
* @return 适合在JSON中显示的字符串
* @since 3.3.1
*/
public static String quote(final String string, final boolean isWrap) {
return quote(string, new StringWriter(), isWrap).toString();
}
/**
* 对所有双引号做转义处理使用双反斜杠做转义<br>
* 为了能在HTML中较好的显示会将&lt;/转义为&lt;\/<br>
* JSON字符串中不能包含控制字符和未经转义的引号和反斜杠
*
* @param str 字符串
* @param writer Writer
* @return Writer
* @throws IORuntimeException IO异常
*/
public static Writer quote(final String str, final Writer writer) throws IORuntimeException {
return quote(str, writer, true);
}
/**
* 对所有双引号做转义处理使用双反斜杠做转义<br>
* 为了能在HTML中较好的显示会将&lt;/转义为&lt;\/<br>
* JSON字符串中不能包含控制字符和未经转义的引号和反斜杠
*
* @param str 字符串
* @param writer Writer
* @param isWrap 是否使用双引号包装字符串
* @return Writer
* @throws IORuntimeException IO异常
* @since 3.3.1
*/
public static Writer quote(final String str, final Writer writer, final boolean isWrap) throws IORuntimeException {
try {
return doQuote(str, writer, isWrap);
} catch (IOException e) {
throw new IORuntimeException(e);
}
}
/**
* 转义显示不可见字符
*
* @param str 字符串
* @return 转义后的字符串
*/
public static String escape(final String str) {
if (StrUtil.isEmpty(str)) {
return str;
}
final int len = str.length();
final StringBuilder builder = new StringBuilder(len);
char c;
for (int i = 0; i < len; i++) {
c = str.charAt(i);
builder.append(escape(c));
}
return builder.toString();
} }
/** /**
@ -286,4 +372,82 @@ public final class InternalJSONUtil {
} }
return rawHashMap; return rawHashMap;
} }
// --------------------------------------------------------------------------------------------- Private method start
/**
* 对所有双引号做转义处理使用双反斜杠做转义<br>
* 为了能在HTML中较好的显示会将&lt;/转义为&lt;\/<br>
* JSON字符串中不能包含控制字符和未经转义的引号和反斜杠
*
* @param str 字符串
* @param writer Writer
* @param isWrap 是否使用双引号包装字符串
* @return Writer
* @throws IOException IO异常
* @since 3.3.1
*/
private static Writer doQuote(final String str, final Writer writer, final boolean isWrap) throws IOException {
if (StrUtil.isEmpty(str)) {
if (isWrap) {
writer.write("\"\"");
}
return writer;
}
char c; // 当前字符
final int len = str.length();
if (isWrap) {
writer.write('"');
}
for (int i = 0; i < len; i++) {
c = str.charAt(i);
switch (c) {
case '\\':
case '"':
writer.write("\\");
writer.write(c);
break;
default:
writer.write(escape(c));
}
}
if (isWrap) {
writer.write('"');
}
return writer;
}
/**
* 转义不可见字符<br>
* <a href="https://en.wikibooks.org/wiki/Unicode/Character_reference/0000-0FFF">https://en.wikibooks.org/wiki/Unicode/Character_reference/0000-0FFF</a>
*
* @param c 字符
* @return 转义后的字符串
*/
private static String escape(final char c) {
switch (c) {
case '\b':
return "\\b";
case '\t':
return "\\t";
case '\n':
return "\\n";
case '\f':
return "\\f";
case '\r':
return "\\r";
default:
if (c < StrUtil.C_SPACE || //
(c >= '\u0080' && c <= '\u00a0') || //
(c >= '\u2000' && c <= '\u2010') || //
(c >= '\u2028' && c <= '\u202F') || //
(c >= '\u2066' && c <= '\u206F')//
) {
return HexUtil.toUnicodeHex(c);
} else {
return Character.toString(c);
}
}
}
// --------------------------------------------------------------------------------------------- Private method end
} }

View File

@ -1,7 +1,7 @@
package cn.hutool.json; package cn.hutool.json;
import cn.hutool.core.bean.BeanPath; import cn.hutool.core.bean.BeanPath;
import cn.hutool.json.convert.JSONConverter; import cn.hutool.json.convert.JSONConverterOld;
import java.io.Serializable; import java.io.Serializable;
import java.io.StringWriter; import java.io.StringWriter;
@ -169,6 +169,6 @@ public interface JSON extends Cloneable, Serializable {
* @since 4.3.2 * @since 4.3.2
*/ */
default <T> T toBean(final Type type) { default <T> T toBean(final Type type) {
return JSONConverter.jsonConvert(type, this, getConfig()); return JSONConverterOld.jsonConvert(type, this, getConfig());
} }
} }

View File

@ -8,7 +8,7 @@ import cn.hutool.core.lang.mutable.MutableEntry;
import cn.hutool.core.lang.mutable.MutableObj; import cn.hutool.core.lang.mutable.MutableObj;
import cn.hutool.core.text.StrJoiner; import cn.hutool.core.text.StrJoiner;
import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjUtil;
import cn.hutool.json.convert.JSONConverter; import cn.hutool.json.convert.JSONConverterOld;
import cn.hutool.json.mapper.ArrayMapper; import cn.hutool.json.mapper.ArrayMapper;
import cn.hutool.json.serialize.JSONWriter; import cn.hutool.json.serialize.JSONWriter;
@ -195,7 +195,7 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
@Override @Override
public <T> T getByPath(final String expression, final Class<T> resultType) { public <T> T getByPath(final String expression, final Class<T> resultType) {
return JSONConverter.jsonConvert(resultType, getByPath(expression), getConfig()); return JSONConverterOld.jsonConvert(resultType, getByPath(expression), getConfig());
} }
/** /**

View File

@ -3,7 +3,7 @@ package cn.hutool.json;
import cn.hutool.core.convert.ConvertException; import cn.hutool.core.convert.ConvertException;
import cn.hutool.core.lang.getter.OptNullBasicTypeFromObjectGetter; import cn.hutool.core.lang.getter.OptNullBasicTypeFromObjectGetter;
import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjUtil;
import cn.hutool.json.convert.JSONConverter; import cn.hutool.json.convert.JSONConverterOld;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Date; import java.util.Date;
@ -55,7 +55,7 @@ public interface JSONGetter<K> extends OptNullBasicTypeFromObjectGetter<K> {
* @since 4.2.2 * @since 4.2.2
*/ */
default String getStrEscaped(final K key, final String defaultValue) { default String getStrEscaped(final K key, final String defaultValue) {
return JSONUtil.escape(getStr(key, defaultValue)); return InternalJSONUtil.escape(getStr(key, defaultValue));
} }
/** /**
@ -169,6 +169,6 @@ public interface JSONGetter<K> extends OptNullBasicTypeFromObjectGetter<K> {
return null; return null;
} }
return JSONConverter.jsonConvert(type, value, getConfig()); return JSONConverterOld.jsonConvert(type, value, getConfig());
} }
} }

View File

@ -5,7 +5,7 @@ import cn.hutool.core.lang.mutable.MutableEntry;
import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.MapUtil;
import cn.hutool.core.map.MapWrapper; import cn.hutool.core.map.MapWrapper;
import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjUtil;
import cn.hutool.json.convert.JSONConverter; import cn.hutool.json.convert.JSONConverterOld;
import cn.hutool.json.mapper.ObjectMapper; import cn.hutool.json.mapper.ObjectMapper;
import cn.hutool.json.serialize.JSONWriter; import cn.hutool.json.serialize.JSONWriter;
@ -185,7 +185,7 @@ public class JSONObject extends MapWrapper<String, Object> implements JSON, JSON
@Override @Override
public <T> T getByPath(final String expression, final Class<T> resultType) { public <T> T getByPath(final String expression, final Class<T> resultType) {
return JSONConverter.jsonConvert(resultType, getByPath(expression), getConfig()); return JSONConverterOld.jsonConvert(resultType, getByPath(expression), getConfig());
} }
/** /**
@ -287,7 +287,7 @@ public class JSONObject extends MapWrapper<String, Object> implements JSON, JSON
} else if (object instanceof JSONArray) { } else if (object instanceof JSONArray) {
((JSONArray) object).set(value); ((JSONArray) object).set(value);
} else { } else {
this.set(key, JSONUtil.createArray(this.config).set(object).set(value)); this.set(key, JSONUtil.ofArray(this.config).set(object).set(value));
} }
return this; return this;
} }
@ -316,7 +316,7 @@ public class JSONObject extends MapWrapper<String, Object> implements JSON, JSON
} else if (value instanceof Float) { } else if (value instanceof Float) {
this.set(key, (Float) value + 1); this.set(key, (Float) value + 1);
} else { } else {
throw new JSONException("Unable to increment [" + JSONUtil.quote(key) + "]."); throw new JSONException("Unable to increment [" + InternalJSONUtil.quote(key) + "].");
} }
return this; return this;
} }

View File

@ -1,7 +1,7 @@
package cn.hutool.json; package cn.hutool.json;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.convert.JSONConverter; import cn.hutool.json.convert.JSONConverterOld;
import cn.hutool.json.serialize.JSONDeserializer; import cn.hutool.json.serialize.JSONDeserializer;
import cn.hutool.json.serialize.JSONString; import cn.hutool.json.serialize.JSONString;
@ -29,7 +29,7 @@ public class JSONSupport implements JSONString, JSONDeserializer<Object> {
*/ */
@Override @Override
public Object deserialize(final JSON json) { public Object deserialize(final JSON json) {
final JSONSupport support = JSONConverter.jsonToBean(getClass(), json, false); final JSONSupport support = JSONConverterOld.jsonToBean(getClass(), json, false);
BeanUtil.copyProperties(support, this); BeanUtil.copyProperties(support, this);
return this; return this;
} }

View File

@ -1,13 +1,11 @@
package cn.hutool.json; package cn.hutool.json;
import cn.hutool.core.codec.HexUtil; import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.file.FileReader;
import cn.hutool.core.map.MapWrapper;
import cn.hutool.core.reflect.TypeReference; import cn.hutool.core.reflect.TypeReference;
import cn.hutool.core.text.StrUtil; import cn.hutool.core.text.StrUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjUtil;
import cn.hutool.json.convert.JSONConverter;
import cn.hutool.json.serialize.GlobalSerializeMapping; import cn.hutool.json.serialize.GlobalSerializeMapping;
import cn.hutool.json.serialize.JSONArraySerializer; import cn.hutool.json.serialize.JSONArraySerializer;
import cn.hutool.json.serialize.JSONDeserializer; import cn.hutool.json.serialize.JSONDeserializer;
@ -16,11 +14,10 @@ import cn.hutool.json.xml.JSONXMLUtil;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.StringWriter; import java.io.Reader;
import java.io.Writer; import java.io.Writer;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.List; import java.util.List;
/** /**
@ -37,7 +34,7 @@ public class JSONUtil {
* *
* @return JSONObject * @return JSONObject
*/ */
public static JSONObject createObj() { public static JSONObject ofObj() {
return new JSONObject(); return new JSONObject();
} }
@ -48,7 +45,7 @@ public class JSONUtil {
* @return JSONObject * @return JSONObject
* @since 5.2.5 * @since 5.2.5
*/ */
public static JSONObject createObj(final JSONConfig config) { public static JSONObject ofObj(final JSONConfig config) {
return new JSONObject(config); return new JSONObject(config);
} }
@ -57,7 +54,7 @@ public class JSONUtil {
* *
* @return JSONArray * @return JSONArray
*/ */
public static JSONArray createArray() { public static JSONArray ofArray() {
return new JSONArray(); return new JSONArray();
} }
@ -68,7 +65,7 @@ public class JSONUtil {
* @return JSONArray * @return JSONArray
* @since 5.2.5 * @since 5.2.5
*/ */
public static JSONArray createArray(final JSONConfig config) { public static JSONArray ofArray(final JSONConfig config) {
return new JSONArray(config); return new JSONArray(config);
} }
@ -131,18 +128,6 @@ public class JSONUtil {
return new JSONArray(arrayOrCollection, config); return new JSONArray(arrayOrCollection, config);
} }
/**
* JSON字符串转JSONArray
*
* @param arrayOrCollection 数组或集合对象
* @param ignoreNullValue 是否忽略空值
* @return JSONArray
* @since 3.2.3
*/
public static JSONArray parseArray(final Object arrayOrCollection, final boolean ignoreNullValue) {
return new JSONArray(arrayOrCollection, JSONConfig.of().setIgnoreNullValue(ignoreNullValue));
}
/** /**
* 转换对象为JSON如果用户不配置JSONConfig则JSON的有序与否与传入对象有关<br> * 转换对象为JSON如果用户不配置JSONConfig则JSON的有序与否与传入对象有关<br>
* 支持的对象 * 支持的对象
@ -156,7 +141,7 @@ public class JSONUtil {
* @return JSON * @return JSON
*/ */
public static JSON parse(final Object obj) { public static JSON parse(final Object obj) {
return parse(obj, null); return JSONConverter.INSTANCE.convert(obj);
} }
/** /**
@ -174,25 +159,7 @@ public class JSONUtil {
* @since 5.3.1 * @since 5.3.1
*/ */
public static JSON parse(final Object obj, final JSONConfig config) { public static JSON parse(final Object obj, final JSONConfig config) {
if (null == obj) { return JSONConverter.of(config).convert(obj);
return null;
}
final JSON json;
if (obj instanceof JSON) {
json = (JSON) obj;
} else if (obj instanceof CharSequence) {
final String jsonStr = StrUtil.trim((CharSequence) obj);
json = isTypeJSONArray(jsonStr) ? parseArray(jsonStr, config) : parseObj(jsonStr, config);
} else if (obj instanceof MapWrapper) {
// MapWrapper实现了Iterable会被当作JSONArray此处做修正
json = parseObj(obj, config);
} else if (obj instanceof Iterable || obj instanceof Iterator || ArrayUtil.isArray(obj)) {// 列表
json = parseArray(obj, config);
} else {// 对象
json = parseObj(obj, config);
}
return json;
} }
/** /**
@ -204,11 +171,9 @@ public class JSONUtil {
public static JSONObject parseFromXml(final String xmlStr) { public static JSONObject parseFromXml(final String xmlStr) {
return JSONXMLUtil.toJSONObject(xmlStr); return JSONXMLUtil.toJSONObject(xmlStr);
} }
// -------------------------------------------------------------------- Parse end // -------------------------------------------------------------------- Parse end
// -------------------------------------------------------------------- Read start // -------------------------------------------------------------------- Read start
/** /**
* 读取JSON * 读取JSON
* *
@ -218,7 +183,11 @@ public class JSONUtil {
* @throws IORuntimeException IO异常 * @throws IORuntimeException IO异常
*/ */
public static JSON readJSON(final File file, final Charset charset) throws IORuntimeException { public static JSON readJSON(final File file, final Charset charset) throws IORuntimeException {
return parse(FileReader.of(file, charset).readString()); try (final Reader reader = FileUtil.getReader(file, charset)) {
return parse(reader);
} catch (final IOException e) {
throw new IORuntimeException(e);
}
} }
/** /**
@ -230,7 +199,11 @@ public class JSONUtil {
* @throws IORuntimeException IO异常 * @throws IORuntimeException IO异常
*/ */
public static JSONObject readJSONObject(final File file, final Charset charset) throws IORuntimeException { public static JSONObject readJSONObject(final File file, final Charset charset) throws IORuntimeException {
return parseObj(FileReader.of(file, charset).readString()); try (final Reader reader = FileUtil.getReader(file, charset)) {
return parseObj(reader);
} catch (final IOException e) {
throw new IORuntimeException(e);
}
} }
/** /**
@ -242,7 +215,11 @@ public class JSONUtil {
* @throws IORuntimeException IO异常 * @throws IORuntimeException IO异常
*/ */
public static JSONArray readJSONArray(final File file, final Charset charset) throws IORuntimeException { public static JSONArray readJSONArray(final File file, final Charset charset) throws IORuntimeException {
return parseArray(FileReader.of(file, charset).readString()); try (final Reader reader = FileUtil.getReader(file, charset)) {
return parseArray(reader);
} catch (final IOException e) {
throw new IORuntimeException(e);
}
} }
// -------------------------------------------------------------------- Read end // -------------------------------------------------------------------- Read end
@ -298,7 +275,7 @@ public class JSONUtil {
if (null == json) { if (null == json) {
return null; return null;
} }
return json.toJSONString(4); return json.toStringPretty();
} }
/** /**
@ -365,6 +342,18 @@ public class JSONUtil {
public static String toXmlStr(final JSON json) { public static String toXmlStr(final JSON json) {
return JSONXMLUtil.toXml(json); return JSONXMLUtil.toXml(json);
} }
/**
* XML转JSONObject<br>
* 转换过程中一些信息可能会丢失JSON中无法区分节点和属性相同的节点将被处理为JSONArray
*
* @param xml XML字符串
* @return JSONObject
* @since 4.0.8
*/
public static JSONObject xmlToJson(final String xml) {
return JSONXMLUtil.toJSONObject(xml);
}
// -------------------------------------------------------------------- toString end // -------------------------------------------------------------------- toString end
// -------------------------------------------------------------------- toBean start // -------------------------------------------------------------------- toBean start
@ -567,116 +556,6 @@ public class JSONUtil {
json.putByPath(expression, value); json.putByPath(expression, value);
} }
/**
* 对所有双引号做转义处理使用双反斜杠做转义<br>
* 为了能在HTML中较好的显示会将&lt;/转义为&lt;\/<br>
* JSON字符串中不能包含控制字符和未经转义的引号和反斜杠
*
* @param string 字符串
* @return 适合在JSON中显示的字符串
*/
public static String quote(final String string) {
return quote(string, true);
}
/**
* 对所有双引号做转义处理使用双反斜杠做转义<br>
* 为了能在HTML中较好的显示会将&lt;/转义为&lt;\/<br>
* JSON字符串中不能包含控制字符和未经转义的引号和反斜杠
*
* @param string 字符串
* @param isWrap 是否使用双引号包装字符串
* @return 适合在JSON中显示的字符串
* @since 3.3.1
*/
public static String quote(final String string, final boolean isWrap) {
final StringWriter sw = new StringWriter();
try {
return quote(string, sw, isWrap).toString();
} catch (final IOException ignored) {
// will never happen - we are writing to a string writer
return StrUtil.EMPTY;
}
}
/**
* 对所有双引号做转义处理使用双反斜杠做转义<br>
* 为了能在HTML中较好的显示会将&lt;/转义为&lt;\/<br>
* JSON字符串中不能包含控制字符和未经转义的引号和反斜杠
*
* @param str 字符串
* @param writer Writer
* @return Writer
* @throws IOException IO异常
*/
public static Writer quote(final String str, final Writer writer) throws IOException {
return quote(str, writer, true);
}
/**
* 对所有双引号做转义处理使用双反斜杠做转义<br>
* 为了能在HTML中较好的显示会将&lt;/转义为&lt;\/<br>
* JSON字符串中不能包含控制字符和未经转义的引号和反斜杠
*
* @param str 字符串
* @param writer Writer
* @param isWrap 是否使用双引号包装字符串
* @return Writer
* @throws IOException IO异常
* @since 3.3.1
*/
public static Writer quote(final String str, final Writer writer, final boolean isWrap) throws IOException {
if (StrUtil.isEmpty(str)) {
if (isWrap) {
writer.write("\"\"");
}
return writer;
}
char c; // 当前字符
final int len = str.length();
if (isWrap) {
writer.write('"');
}
for (int i = 0; i < len; i++) {
c = str.charAt(i);
switch (c) {
case '\\':
case '"':
writer.write("\\");
writer.write(c);
break;
default:
writer.write(escape(c));
}
}
if (isWrap) {
writer.write('"');
}
return writer;
}
/**
* 转义显示不可见字符
*
* @param str 字符串
* @return 转义后的字符串
*/
public static String escape(final String str) {
if (StrUtil.isEmpty(str)) {
return str;
}
final int len = str.length();
final StringBuilder builder = new StringBuilder(len);
char c;
for (int i = 0; i < len; i++) {
c = str.charAt(i);
builder.append(escape(c));
}
return builder.toString();
}
/** /**
* 格式化JSON字符串此方法并不严格检查JSON的格式正确与否 * 格式化JSON字符串此方法并不严格检查JSON的格式正确与否
* *
@ -727,18 +606,6 @@ public class JSONUtil {
return StrUtil.isWrap(StrUtil.trim(str), '[', ']'); return StrUtil.isWrap(StrUtil.trim(str), '[', ']');
} }
/**
* XML转JSONObject<br>
* 转换过程中一些信息可能会丢失JSON中无法区分节点和属性相同的节点将被处理为JSONArray
*
* @param xml XML字符串
* @return JSONObject
* @since 4.0.8
*/
public static JSONObject xmlToJson(final String xml) {
return JSONXMLUtil.toJSONObject(xml);
}
/** /**
* 加入自定义的序列化器 * 加入自定义的序列化器
* *
@ -774,40 +641,4 @@ public class JSONUtil {
public static void putDeserializer(final Type type, final JSONDeserializer<?> deserializer) { public static void putDeserializer(final Type type, final JSONDeserializer<?> deserializer) {
GlobalSerializeMapping.putDeserializer(type, deserializer); GlobalSerializeMapping.putDeserializer(type, deserializer);
} }
// --------------------------------------------------------------------------------------------- Private method start
/**
* 转义不可见字符<br>
* <a href="https://en.wikibooks.org/wiki/Unicode/Character_reference/0000-0FFF">https://en.wikibooks.org/wiki/Unicode/Character_reference/0000-0FFF</a>
*
* @param c 字符
* @return 转义后的字符串
*/
private static String escape(final char c) {
switch (c) {
case '\b':
return "\\b";
case '\t':
return "\\t";
case '\n':
return "\\n";
case '\f':
return "\\f";
case '\r':
return "\\r";
default:
if (c < StrUtil.C_SPACE || //
(c >= '\u0080' && c <= '\u00a0') || //
(c >= '\u2000' && c <= '\u2010') || //
(c >= '\u2028' && c <= '\u202F') || //
(c >= '\u2066' && c <= '\u206F')//
) {
return HexUtil.toUnicodeHex(c);
} else {
return Character.toString(c);
}
}
}
// --------------------------------------------------------------------------------------------- Private method end
} }

View File

@ -1,194 +1,90 @@
package cn.hutool.json.convert; package cn.hutool.json.convert;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.ConvertException; import cn.hutool.core.convert.ConvertException;
import cn.hutool.core.convert.Converter; import cn.hutool.core.convert.Converter;
import cn.hutool.core.convert.CompositeConverter; import cn.hutool.core.map.MapWrapper;
import cn.hutool.core.convert.impl.BeanConverter;
import cn.hutool.core.convert.impl.DateConverter;
import cn.hutool.core.convert.impl.TemporalAccessorConverter;
import cn.hutool.core.reflect.ConstructorUtil;
import cn.hutool.core.reflect.TypeUtil;
import cn.hutool.core.text.StrUtil; import cn.hutool.core.text.StrUtil;
import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ArrayUtil;
import cn.hutool.json.InternalJSONUtil;
import cn.hutool.json.JSON; import cn.hutool.json.JSON;
import cn.hutool.json.JSONArray; import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONConfig; import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import cn.hutool.json.serialize.GlobalSerializeMapping;
import cn.hutool.json.serialize.JSONDeserializer;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.time.temporal.TemporalAccessor; import java.util.Iterator;
import java.util.Date;
/** /**
* JSON转换器 * JSON转换器实现Object对象转换为{@link JSON}支持的对象
* <ul>
* <li>String: 转换为相应的对象</li>
* <li>ArrayIterableIterator转换为JSONArray</li>
* <li>Bean对象转为JSONObject</li>
* </ul>
* *
* @author looly * @author looly
* @since 4.2.2 * @since 6.0.0
*/ */
public class JSONConverter implements Converter { public class JSONConverter implements Converter {
public static final JSONConverter INSTANCE = new JSONConverter(null);
public static JSONConverter INSTANCE = new JSONConverter(); /**
* 创建JSON转换器
*
* @param config JSON配置
* @return JSONConverter
*/
public static JSONConverter of(final JSONConfig config) {
return new JSONConverter(config);
}
private static final CompositeConverter registry; private final JSONConfig config;
static {
// 注册到转换中心 /**
registry = new CompositeConverter(); * 构造
registry.putCustom(JSON.class, INSTANCE); *
registry.putCustom(JSONObject.class, INSTANCE); * @param config JSON配置
registry.putCustom(JSONArray.class, INSTANCE); */
public JSONConverter(final JSONConfig config) {
this.config = config;
}
/**
* 实现Object对象转换为{@link JSON}支持的对象
* <ul>
* <li>String: 转换为相应的对象</li>
* <li>ArrayIterableIterator转换为JSONArray</li>
* <li>Bean对象转为JSONObject</li>
* </ul>
*
* @param obj 被转换的对象
* @return 转换后的对象
* @throws ConvertException 转换异常
*/
public JSON convert(final Object obj) throws ConvertException {
return (JSON) convert(null, obj);
} }
@Override @Override
public Object convert(final Type targetType, final Object value) throws ConvertException { public Object convert(final Type targetType, final Object obj) throws ConvertException {
return JSONUtil.parse(value); if (null == obj) {
}
/**
* 转换值为指定类型可选是否不抛异常转换<br>
* 当转换失败时返回默认值
*
* @param <T> 目标类型
* @param type 目标类型
* @param value
* @param defaultValue 默认值
* @param quietly 是否静默转换true不抛异常
* @return 转换后的值
* @since 5.3.2
*/
public static <T> T convertWithCheck(final Type type, final Object value, final T defaultValue, final boolean quietly) {
try {
return registry.convert(type, value, defaultValue);
} catch (final Exception e) {
if(quietly){
return defaultValue;
}
throw e;
}
}
/**
* JSON递归转换<br>
* 首先尝试JDK类型转换如果失败尝试JSON转Bean<br>
* 如果遇到{@link JSONDeserializer}则调用其{@link JSONDeserializer#deserialize(JSON)}方法转换
*
* @param <T> 转换后的对象类型
* @param targetType 目标类型
* @param value
* @param config JSON配置项
* @return 目标类型的值
* @throws ConvertException 转换失败
*/
@SuppressWarnings("unchecked")
public static <T> T jsonConvert(final Type targetType, final Object value, final JSONConfig config) throws ConvertException {
if (null == value) {
return null; return null;
} }
final JSON json;
// since 5.7.8增加自定义Bean反序列化接口和特殊对象的自定义转换 if (obj instanceof JSON) {
if (targetType instanceof Class) { json = (JSON) obj;
final Class<?> targetClass = (Class<?>) targetType; } else if (obj instanceof CharSequence) {
if (targetClass.isInstance(value)) { final String jsonStr = StrUtil.trim((CharSequence) obj);
return (T) value; json = JSONUtil.isTypeJSONArray(jsonStr) ? new JSONArray(jsonStr, config) : new JSONObject(jsonStr, config);
} else if (JSONDeserializer.class.isAssignableFrom(targetClass)) { } else if (obj instanceof MapWrapper) {
// 自定义反序列化 // MapWrapper实现了Iterable会被当作JSONArray此处做修正
if (value instanceof JSON) { json = new JSONObject(obj, config);
final JSONDeserializer<T> target = (JSONDeserializer<T>) ConstructorUtil.newInstanceIfPossible(targetClass); } else if (obj instanceof Iterable || obj instanceof Iterator || ArrayUtil.isArray(obj)) {// 列表
if (null == target) { json = new JSONArray(obj, config);
throw new ConvertException("Can not instance target: [{}]", targetType); } else {// 对象
} json = new JSONObject(obj, config);
return target.deserialize((JSON) value);
}
} else if (targetClass.isAssignableFrom(Date.class) || targetClass.isAssignableFrom(TemporalAccessor.class)) {
// 用户指定了日期格式获取日期属性时使用对应格式
final String valueStr = convertWithCheck(String.class, value, null, true);
if (null == valueStr) {
return null;
}
// 日期转换支持自定义日期格式
final String format = getDateFormat(config);
if (null != format) {
if (targetClass.isAssignableFrom(Date.class)) {
return (T) new DateConverter(format).convert(targetClass, valueStr);
} else {
return (T) new TemporalAccessorConverter(format).convert(targetClass, valueStr);
}
}
}
} }
return jsonToBean(targetType, value, null != config && config.isIgnoreError()); return json;
}
/**
* JSON递归转换为Bean<br>
* 首先尝试JDK类型转换如果失败尝试JSON转Bean
*
* @param <T> 转换后的对象类型
* @param targetType 目标类型
* @param value JSON格式
* @param ignoreError 是否忽略转换错误
* @return 目标类型的值
* @throws ConvertException 转换失败
* @since 5.7.10
*/
@SuppressWarnings("unchecked")
public static <T> T jsonToBean(final Type targetType, final Object value, final boolean ignoreError) throws ConvertException {
if (null == value) {
return null;
}
if (value instanceof JSON) {
final JSON valueJson = (JSON) value;
// 全局自定义反序列化
final JSONDeserializer<?> deserializer = GlobalSerializeMapping.getDeserializer(targetType);
if (null != deserializer) {
return (T) deserializer.deserialize(valueJson);
}
// issue#2212@Github
// 在JSONObject转Bean时读取JSONObject本身的配置文件
if (targetType instanceof Class && BeanUtil.hasSetter((Class<?>) targetType)) {
final JSONConfig config = valueJson.getConfig();
final Converter converter = new BeanConverter(InternalJSONUtil.toCopyOptions(config).setIgnoreError(ignoreError));
return ignoreError ? converter.convert(targetType, value, null)
: (T) converter.convert(targetType, value);
}
}
final T targetValue = convertWithCheck(targetType, value, null, ignoreError);
if (null == targetValue && false == ignoreError) {
if (StrUtil.isBlankIfStr(value)) {
// 对于传入空字符串的情况如果转换的目标对象是非字符串或非原始类型转换器会返回false
// 此处特殊处理认为返回null属于正常情况
return null;
}
throw new ConvertException("Can not convert {} to type {}", value, ObjUtil.defaultIfNull(TypeUtil.getClass(targetType), targetType));
}
return targetValue;
}
/**
* 获取配置文件中的日期格式无格式返回{@code null}
*
* @param config JSON配置
* @return 日期格式无返回{@code null}
*/
private static String getDateFormat(final JSONConfig config) {
if (null != config) {
final String format = config.getDateFormat();
if (StrUtil.isNotBlank(format)) {
return format;
}
}
return null;
} }
} }

View File

@ -0,0 +1,194 @@
package cn.hutool.json.convert;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.ConvertException;
import cn.hutool.core.convert.Converter;
import cn.hutool.core.convert.CompositeConverter;
import cn.hutool.core.convert.impl.BeanConverter;
import cn.hutool.core.convert.impl.DateConverter;
import cn.hutool.core.convert.impl.TemporalAccessorConverter;
import cn.hutool.core.reflect.ConstructorUtil;
import cn.hutool.core.reflect.TypeUtil;
import cn.hutool.core.text.StrUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.json.InternalJSONUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.json.serialize.GlobalSerializeMapping;
import cn.hutool.json.serialize.JSONDeserializer;
import java.lang.reflect.Type;
import java.time.temporal.TemporalAccessor;
import java.util.Date;
/**
* JSON转换器
*
* @author looly
* @since 4.2.2
*/
public class JSONConverterOld implements Converter {
public static final JSONConverterOld INSTANCE = new JSONConverterOld();
private static final CompositeConverter registry;
static {
// 注册到转换中心
registry = new CompositeConverter();
registry.putCustom(JSON.class, INSTANCE);
registry.putCustom(JSONObject.class, INSTANCE);
registry.putCustom(JSONArray.class, INSTANCE);
}
@Override
public Object convert(final Type targetType, final Object value) throws ConvertException {
return JSONUtil.parse(value);
}
/**
* 转换值为指定类型可选是否不抛异常转换<br>
* 当转换失败时返回默认值
*
* @param <T> 目标类型
* @param type 目标类型
* @param value
* @param defaultValue 默认值
* @param quietly 是否静默转换true不抛异常
* @return 转换后的值
* @since 5.3.2
*/
public static <T> T convertWithCheck(final Type type, final Object value, final T defaultValue, final boolean quietly) {
try {
return registry.convert(type, value, defaultValue);
} catch (final Exception e) {
if(quietly){
return defaultValue;
}
throw e;
}
}
/**
* JSON递归转换<br>
* 首先尝试JDK类型转换如果失败尝试JSON转Bean<br>
* 如果遇到{@link JSONDeserializer}则调用其{@link JSONDeserializer#deserialize(JSON)}方法转换
*
* @param <T> 转换后的对象类型
* @param targetType 目标类型
* @param value
* @param config JSON配置项
* @return 目标类型的值
* @throws ConvertException 转换失败
*/
@SuppressWarnings("unchecked")
public static <T> T jsonConvert(final Type targetType, final Object value, final JSONConfig config) throws ConvertException {
if (null == value) {
return null;
}
// since 5.7.8增加自定义Bean反序列化接口和特殊对象的自定义转换
if (targetType instanceof Class) {
final Class<?> targetClass = (Class<?>) targetType;
if (targetClass.isInstance(value)) {
return (T) value;
} else if (JSONDeserializer.class.isAssignableFrom(targetClass)) {
// 自定义反序列化
if (value instanceof JSON) {
final JSONDeserializer<T> target = (JSONDeserializer<T>) ConstructorUtil.newInstanceIfPossible(targetClass);
if (null == target) {
throw new ConvertException("Can not instance target: [{}]", targetType);
}
return target.deserialize((JSON) value);
}
} else if (targetClass.isAssignableFrom(Date.class) || targetClass.isAssignableFrom(TemporalAccessor.class)) {
// 用户指定了日期格式获取日期属性时使用对应格式
final String valueStr = convertWithCheck(String.class, value, null, true);
if (null == valueStr) {
return null;
}
// 日期转换支持自定义日期格式
final String format = getDateFormat(config);
if (null != format) {
if (targetClass.isAssignableFrom(Date.class)) {
return (T) new DateConverter(format).convert(targetClass, valueStr);
} else {
return (T) new TemporalAccessorConverter(format).convert(targetClass, valueStr);
}
}
}
}
return jsonToBean(targetType, value, null != config && config.isIgnoreError());
}
/**
* JSON递归转换为Bean<br>
* 首先尝试JDK类型转换如果失败尝试JSON转Bean
*
* @param <T> 转换后的对象类型
* @param targetType 目标类型
* @param value JSON格式
* @param ignoreError 是否忽略转换错误
* @return 目标类型的值
* @throws ConvertException 转换失败
* @since 5.7.10
*/
@SuppressWarnings("unchecked")
public static <T> T jsonToBean(final Type targetType, final Object value, final boolean ignoreError) throws ConvertException {
if (null == value) {
return null;
}
if (value instanceof JSON) {
final JSON valueJson = (JSON) value;
// 全局自定义反序列化
final JSONDeserializer<?> deserializer = GlobalSerializeMapping.getDeserializer(targetType);
if (null != deserializer) {
return (T) deserializer.deserialize(valueJson);
}
// issue#2212@Github
// 在JSONObject转Bean时读取JSONObject本身的配置文件
if (targetType instanceof Class && BeanUtil.hasSetter((Class<?>) targetType)) {
final JSONConfig config = valueJson.getConfig();
final Converter converter = new BeanConverter(InternalJSONUtil.toCopyOptions(config).setIgnoreError(ignoreError));
return ignoreError ? converter.convert(targetType, value, null)
: (T) converter.convert(targetType, value);
}
}
final T targetValue = convertWithCheck(targetType, value, null, ignoreError);
if (null == targetValue && false == ignoreError) {
if (StrUtil.isBlankIfStr(value)) {
// 对于传入空字符串的情况如果转换的目标对象是非字符串或非原始类型转换器会返回false
// 此处特殊处理认为返回null属于正常情况
return null;
}
throw new ConvertException("Can not convert {} to type {}", value, ObjUtil.defaultIfNull(TypeUtil.getClass(targetType), targetType));
}
return targetValue;
}
/**
* 获取配置文件中的日期格式无格式返回{@code null}
*
* @param config JSON配置
* @return 日期格式无返回{@code null}
*/
private static String getDateFormat(final JSONConfig config) {
if (null != config) {
final String format = config.getDateFormat();
if (StrUtil.isNotBlank(format)) {
return format;
}
}
return null;
}
}

View File

@ -16,7 +16,7 @@ public class JSONDeserializerConverter extends AbstractConverter {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@Override @Override
protected Object convertInternal(Class<?> targetClass, Object value) { protected Object convertInternal(final Class<?> targetClass, final Object value) {
// 自定义反序列化 // 自定义反序列化
if (value instanceof JSON) { if (value instanceof JSON) {
final JSONDeserializer<?> target = (JSONDeserializer<?>) ConstructorUtil.newInstanceIfPossible(targetClass); final JSONDeserializer<?> target = (JSONDeserializer<?>) ConstructorUtil.newInstanceIfPossible(targetClass);

View File

@ -0,0 +1,7 @@
/**
* JSON中对象值类型转换封装
*
* @author Looly
* @since 6.0.0
*/
package cn.hutool.json.convert;

View File

@ -5,8 +5,8 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TemporalAccessorUtil; import cn.hutool.core.date.TemporalAccessorUtil;
import cn.hutool.core.date.format.GlobalCustomFormat; import cn.hutool.core.date.format.GlobalCustomFormat;
import cn.hutool.core.text.StrUtil; import cn.hutool.core.text.StrUtil;
import cn.hutool.json.InternalJSONUtil;
import cn.hutool.json.JSONConfig; import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONUtil;
import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalAccessor;
import java.util.Calendar; import java.util.Calendar;
@ -55,7 +55,7 @@ public class DateJSONString implements JSONString {
return dateStr; return dateStr;
} }
//用户定义了日期格式 //用户定义了日期格式
return JSONUtil.quote(dateStr); return InternalJSONUtil.quote(dateStr);
} }
//默认使用时间戳 //默认使用时间戳

View File

@ -8,10 +8,10 @@ import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.math.NumberUtil; import cn.hutool.core.math.NumberUtil;
import cn.hutool.core.text.StrUtil; import cn.hutool.core.text.StrUtil;
import cn.hutool.core.util.CharUtil; import cn.hutool.core.util.CharUtil;
import cn.hutool.json.InternalJSONUtil;
import cn.hutool.json.JSON; import cn.hutool.json.JSON;
import cn.hutool.json.JSONConfig; import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONException; import cn.hutool.json.JSONException;
import cn.hutool.json.JSONUtil;
import java.io.IOException; import java.io.IOException;
import java.io.Writer; import java.io.Writer;
@ -137,7 +137,7 @@ public class JSONWriter extends Writer {
// 换行缩进 // 换行缩进
//noinspection resource //noinspection resource
writeLF().writeSpace(indentFactor + indent); writeLF().writeSpace(indentFactor + indent);
return writeRaw(JSONUtil.quote(key)); return writeRaw(InternalJSONUtil.quote(key));
} }
/** /**
@ -300,11 +300,7 @@ public class JSONWriter extends Writer {
* @param csq 字符串 * @param csq 字符串
*/ */
private void writeQuoteStrValue(final String csq) { private void writeQuoteStrValue(final String csq) {
try { InternalJSONUtil.quote(csq, writer);
JSONUtil.quote(csq, writer);
} catch (final IOException e) {
throw new IORuntimeException(e);
}
} }
/** /**
@ -386,7 +382,7 @@ public class JSONWriter extends Writer {
return dateStr; return dateStr;
} }
//用户定义了日期格式 //用户定义了日期格式
return JSONUtil.quote(dateStr); return InternalJSONUtil.quote(dateStr);
} }
//默认使用时间戳 //默认使用时间戳

View File

@ -29,7 +29,7 @@ public class CustomSerializeTest {
final CustomBean customBean = new CustomBean(); final CustomBean customBean = new CustomBean();
customBean.name = "testName"; customBean.name = "testName";
final JSONObject obj = JSONUtil.createObj().set("customBean", customBean); final JSONObject obj = JSONUtil.ofObj().set("customBean", customBean);
Assert.assertEquals("testName", obj.getJSONObject("customBean").getStr("customName")); Assert.assertEquals("testName", obj.getJSONObject("customBean").getStr("customName"));
} }

View File

@ -6,7 +6,7 @@ import org.junit.Test;
public class IssueI59LW4Test { public class IssueI59LW4Test {
@Test @Test
public void bytesTest(){ public void bytesTest(){
final JSONObject jsonObject = JSONUtil.createObj().set("bytes", new byte[]{1}); final JSONObject jsonObject = JSONUtil.ofObj().set("bytes", new byte[]{1});
Assert.assertEquals("{\"bytes\":[1]}", jsonObject.toString()); Assert.assertEquals("{\"bytes\":[1]}", jsonObject.toString());
final byte[] bytes = jsonObject.getBytes("bytes"); final byte[] bytes = jsonObject.getBytes("bytes");
@ -15,7 +15,7 @@ public class IssueI59LW4Test {
@Test @Test
public void bytesInJSONArrayTest(){ public void bytesInJSONArrayTest(){
final JSONArray jsonArray = JSONUtil.createArray().set(new byte[]{1}); final JSONArray jsonArray = JSONUtil.ofArray().set(new byte[]{1});
Assert.assertEquals("[[1]]", jsonArray.toString()); Assert.assertEquals("[[1]]", jsonArray.toString());
final byte[] bytes = jsonArray.getBytes(0); final byte[] bytes = jsonArray.getBytes(0);

View File

@ -22,12 +22,11 @@ import java.util.Map;
* JSONArray单元测试 * JSONArray单元测试
* *
* @author Looly * @author Looly
*
*/ */
public class JSONArrayTest { public class JSONArrayTest {
@Test() @Test()
public void createJSONArrayFromJSONObjectTest(){ public void createJSONArrayFromJSONObjectTest() {
// JSONObject实现了Iterable接口可以转换为JSONArray // JSONObject实现了Iterable接口可以转换为JSONArray
final JSONObject jsonObject = new JSONObject(); final JSONObject jsonObject = new JSONObject();
@ -41,7 +40,7 @@ public class JSONArrayTest {
} }
@Test @Test
public void addNullTest(){ public void addNullTest() {
final List<String> aaa = ListUtil.view("aaa", null); final List<String> aaa = ListUtil.view("aaa", null);
final String jsonStr = JSONUtil.toJsonStr(JSONUtil.parse(aaa, final String jsonStr = JSONUtil.toJsonStr(JSONUtil.parse(aaa,
JSONConfig.of().setIgnoreNullValue(false))); JSONConfig.of().setIgnoreNullValue(false)));
@ -51,7 +50,7 @@ public class JSONArrayTest {
@Test @Test
public void addTest() { public void addTest() {
// 方法1 // 方法1
final JSONArray array = JSONUtil.createArray(); final JSONArray array = JSONUtil.ofArray();
// 方法2 // 方法2
// JSONArray array = new JSONArray(); // JSONArray array = new JSONArray();
array.add("value1"); array.add("value1");
@ -75,12 +74,12 @@ public class JSONArrayTest {
Assert.assertFalse(jsonArray.getJSONObject(1).containsKey("result")); Assert.assertFalse(jsonArray.getJSONObject(1).containsKey("result"));
// 不忽略null则null的键值对被保留 // 不忽略null则null的键值对被保留
jsonArray = JSONUtil.parseArray(jsonStr, false); jsonArray = JSONUtil.parseArray(jsonStr, JSONConfig.of().setIgnoreNullValue(false));
Assert.assertTrue(jsonArray.getJSONObject(1).containsKey("result")); Assert.assertTrue(jsonArray.getJSONObject(1).containsKey("result"));
} }
@Test @Test
public void parseFileTest() { public void readJSONArrayFromFileTest() {
final JSONArray array = JSONUtil.readJSONArray(FileUtil.file("exam_test.json"), CharsetUtil.UTF_8); final JSONArray array = JSONUtil.readJSONArray(FileUtil.file("exam_test.json"), CharsetUtil.UTF_8);
final JSONObject obj0 = array.getJSONObject(0); final JSONObject obj0 = array.getJSONObject(0);
@ -175,11 +174,12 @@ public class JSONArrayTest {
} }
@Test(expected = ConvertException.class) @Test(expected = ConvertException.class)
public void toListWithErrorTest(){ public void toListWithErrorTest() {
final String json = "[['aaa',{'akey':'avalue','bkey':'bvalue'}]]"; final String json = "[['aaa',{'akey':'avalue','bkey':'bvalue'}]]";
final JSONArray ja = JSONUtil.parseArray(json); final JSONArray ja = JSONUtil.parseArray(json);
ja.toBean(new TypeReference<List<List<KeyBean>>>() {}); ja.toBean(new TypeReference<List<List<KeyBean>>>() {
});
} }
@Test @Test
@ -209,7 +209,7 @@ public class JSONArrayTest {
} }
@Test @Test
public void getByPathTest(){ public void getByPathTest() {
final String jsonStr = "[{\"id\": \"1\",\"name\": \"a\"},{\"id\": \"2\",\"name\": \"b\"}]"; final String jsonStr = "[{\"id\": \"1\",\"name\": \"a\"},{\"id\": \"2\",\"name\": \"b\"}]";
final JSONArray jsonArray = JSONUtil.parseArray(jsonStr); final JSONArray jsonArray = JSONUtil.parseArray(jsonStr);
Assert.assertEquals("b", jsonArray.getByPath("[1].name")); Assert.assertEquals("b", jsonArray.getByPath("[1].name"));
@ -217,7 +217,7 @@ public class JSONArrayTest {
} }
@Test @Test
public void putToIndexTest(){ public void putToIndexTest() {
JSONArray jsonArray = new JSONArray(); JSONArray jsonArray = new JSONArray();
jsonArray.set(3, "test"); jsonArray.set(3, "test");
// 默认忽略null值因此空位无值只有一个值 // 默认忽略null值因此空位无值只有一个值
@ -231,7 +231,7 @@ public class JSONArrayTest {
// https://github.com/dromara/hutool/issues/1858 // https://github.com/dromara/hutool/issues/1858
@Test @Test
public void putTest2(){ public void putTest2() {
final JSONArray jsonArray = new JSONArray(); final JSONArray jsonArray = new JSONArray();
jsonArray.put(0, 1); jsonArray.put(0, 1);
Assert.assertEquals(1, jsonArray.size()); Assert.assertEquals(1, jsonArray.size());
@ -253,8 +253,8 @@ public class JSONArrayTest {
} }
@Test @Test
public void filterIncludeTest(){ public void filterIncludeTest() {
final JSONArray json1 = JSONUtil.createArray() final JSONArray json1 = JSONUtil.ofArray()
.set("value1") .set("value1")
.set("value2") .set("value2")
.set("value3") .set("value3")
@ -265,8 +265,8 @@ public class JSONArrayTest {
} }
@Test @Test
public void filterExcludeTest(){ public void filterExcludeTest() {
final JSONArray json1 = JSONUtil.createArray() final JSONArray json1 = JSONUtil.ofArray()
.set("value1") .set("value1")
.set("value2") .set("value2")
.set("value3") .set("value3")
@ -277,8 +277,8 @@ public class JSONArrayTest {
} }
@Test @Test
public void putNullTest(){ public void putNullTest() {
final JSONArray array = JSONUtil.createArray(JSONConfig.of().setIgnoreNullValue(false)); final JSONArray array = JSONUtil.ofArray(JSONConfig.of().setIgnoreNullValue(false));
array.set(null); array.set(null);
Assert.assertEquals("[null]", array.toString()); Assert.assertEquals("[null]", array.toString());
@ -299,7 +299,7 @@ public class JSONArrayTest {
//noinspection MismatchedQueryAndUpdateOfCollection //noinspection MismatchedQueryAndUpdateOfCollection
final JSONArray array = new JSONArray(jsonArr, null, (mutable) -> { final JSONArray array = new JSONArray(jsonArr, null, (mutable) -> {
final JSONObject o = new JSONObject(mutable.get()); final JSONObject o = new JSONObject(mutable.get());
if("111".equals(o.getStr("id"))){ if ("111".equals(o.getStr("id"))) {
o.set("name", "test1_edit"); o.set("name", "test1_edit");
} }
mutable.set(o); mutable.set(o);

View File

@ -35,22 +35,22 @@ public class JSONNullTest {
@Test @Test
public void setNullTest(){ public void setNullTest(){
// 忽略null // 忽略null
String json1 = JSONUtil.createObj().set("key1", null).toString(); String json1 = JSONUtil.ofObj().set("key1", null).toString();
Assert.assertEquals("{}", json1); Assert.assertEquals("{}", json1);
// 不忽略null // 不忽略null
json1 = JSONUtil.createObj(JSONConfig.of().setIgnoreNullValue(false)).set("key1", null).toString(); json1 = JSONUtil.ofObj(JSONConfig.of().setIgnoreNullValue(false)).set("key1", null).toString();
Assert.assertEquals("{\"key1\":null}", json1); Assert.assertEquals("{\"key1\":null}", json1);
} }
@Test @Test
public void setNullOfJSONArrayTest(){ public void setNullOfJSONArrayTest(){
// 忽略null // 忽略null
String json1 = JSONUtil.createArray().set(null).toString(); String json1 = JSONUtil.ofArray().set(null).toString();
Assert.assertEquals("[]", json1); Assert.assertEquals("[]", json1);
// 不忽略null // 不忽略null
json1 = JSONUtil.createArray(JSONConfig.of().setIgnoreNullValue(false)).set(null).toString(); json1 = JSONUtil.ofArray(JSONConfig.of().setIgnoreNullValue(false)).set(null).toString();
Assert.assertEquals("[null]", json1); Assert.assertEquals("[null]", json1);
} }
} }

View File

@ -66,7 +66,7 @@ public class JSONObjectTest {
*/ */
@Test @Test
public void toStringTest3() { public void toStringTest3() {
final JSONObject json = Objects.requireNonNull(JSONUtil.createObj()// final JSONObject json = Objects.requireNonNull(JSONUtil.ofObj()//
.set("dateTime", DateUtil.parse("2019-05-02 22:12:01")))// .set("dateTime", DateUtil.parse("2019-05-02 22:12:01")))//
.setDateFormat(DatePattern.NORM_DATE_PATTERN); .setDateFormat(DatePattern.NORM_DATE_PATTERN);
Assert.assertEquals("{\"dateTime\":\"2019-05-02\"}", json.toString()); Assert.assertEquals("{\"dateTime\":\"2019-05-02\"}", json.toString());
@ -74,24 +74,24 @@ public class JSONObjectTest {
@Test @Test
public void toStringWithDateTest() { public void toStringWithDateTest() {
JSONObject json = JSONUtil.createObj().set("date", DateUtil.parse("2019-05-08 19:18:21")); JSONObject json = JSONUtil.ofObj().set("date", DateUtil.parse("2019-05-08 19:18:21"));
assert json != null; assert json != null;
Assert.assertEquals("{\"date\":1557314301000}", json.toString()); Assert.assertEquals("{\"date\":1557314301000}", json.toString());
json = Objects.requireNonNull(JSONUtil.createObj().set("date", DateUtil.parse("2019-05-08 19:18:21"))).setDateFormat(DatePattern.NORM_DATE_PATTERN); json = Objects.requireNonNull(JSONUtil.ofObj().set("date", DateUtil.parse("2019-05-08 19:18:21"))).setDateFormat(DatePattern.NORM_DATE_PATTERN);
Assert.assertEquals("{\"date\":\"2019-05-08\"}", json.toString()); Assert.assertEquals("{\"date\":\"2019-05-08\"}", json.toString());
} }
@Test @Test
public void putAllTest() { public void putAllTest() {
final JSONObject json1 = JSONUtil.createObj() final JSONObject json1 = JSONUtil.ofObj()
.set("a", "value1") .set("a", "value1")
.set("b", "value2") .set("b", "value2")
.set("c", "value3") .set("c", "value3")
.set("d", true); .set("d", true);
final JSONObject json2 = JSONUtil.createObj() final JSONObject json2 = JSONUtil.ofObj()
.set("a", "value21") .set("a", "value21")
.set("b", "value22"); .set("b", "value22");
@ -185,12 +185,12 @@ public class JSONObjectTest {
@Test @Test
public void toBeanTest() { public void toBeanTest() {
final JSONObject subJson = JSONUtil.createObj().set("value1", "strValue1").set("value2", "234"); final JSONObject subJson = JSONUtil.ofObj().set("value1", "strValue1").set("value2", "234");
final JSONObject json = JSONUtil.createObj(JSONConfig.of().setIgnoreError(true)).set("strValue", "strTest").set("intValue", 123) final JSONObject json = JSONUtil.ofObj(JSONConfig.of().setIgnoreError(true)).set("strValue", "strTest").set("intValue", 123)
// 测试空字符串转对象 // 测试空字符串转对象
.set("doubleValue", "") .set("doubleValue", "")
.set("beanValue", subJson) .set("beanValue", subJson)
.set("list", JSONUtil.createArray().set("a").set("b")).set("testEnum", "TYPE_A"); .set("list", JSONUtil.ofArray().set("a").set("b")).set("testEnum", "TYPE_A");
final TestBean bean = json.toBean(TestBean.class); final TestBean bean = json.toBean(TestBean.class);
Assert.assertEquals("a", bean.getList().get(0)); Assert.assertEquals("a", bean.getList().get(0));
@ -205,12 +205,12 @@ public class JSONObjectTest {
@Test @Test
public void toBeanNullStrTest() { public void toBeanNullStrTest() {
final JSONObject json = JSONUtil.createObj(JSONConfig.of().setIgnoreError(true))// final JSONObject json = JSONUtil.ofObj(JSONConfig.of().setIgnoreError(true))//
.set("strValue", "null")// .set("strValue", "null")//
.set("intValue", 123)// .set("intValue", 123)//
// 子对象对应"null"字符串如果忽略错误跳过否则抛出转换异常 // 子对象对应"null"字符串如果忽略错误跳过否则抛出转换异常
.set("beanValue", "null")// .set("beanValue", "null")//
.set("list", JSONUtil.createArray().set("a").set("b")); .set("list", JSONUtil.ofArray().set("a").set("b"));
final TestBean bean = json.toBean(TestBean.class); final TestBean bean = json.toBean(TestBean.class);
// 当JSON中为字符串"null"时应被当作字符串处理 // 当JSON中为字符串"null"时应被当作字符串处理
@ -272,10 +272,10 @@ public class JSONObjectTest {
*/ */
@Test @Test
public void toBeanTest6() { public void toBeanTest6() {
final JSONObject json = JSONUtil.createObj() final JSONObject json = JSONUtil.ofObj()
.set("targetUrl", "http://test.com") .set("targetUrl", "http://test.com")
.set("success", "true") .set("success", "true")
.set("result", JSONUtil.createObj() .set("result", JSONUtil.ofObj()
.set("token", "tokenTest") .set("token", "tokenTest")
.set("userId", "测试用户1")); .set("userId", "测试用户1"));
@ -334,7 +334,7 @@ public class JSONObjectTest {
@Test @Test
public void parseBeanTest3() { public void parseBeanTest3() {
final JSONObject json = JSONUtil.createObj() final JSONObject json = JSONUtil.ofObj()
.set("code", 22) .set("code", 22)
.set("data", "{\"jobId\": \"abc\", \"videoUrl\": \"http://a.com/a.mp4\"}"); .set("data", "{\"jobId\": \"abc\", \"videoUrl\": \"http://a.com/a.mp4\"}");
@ -375,7 +375,7 @@ public class JSONObjectTest {
@Test @Test
public void beanTransTest3() { public void beanTransTest3() {
final JSONObject userAJson = JSONUtil.createObj() final JSONObject userAJson = JSONUtil.ofObj()
.set("a", "AValue") .set("a", "AValue")
.set("name", "nameValue") .set("name", "nameValue")
.set("date", "08:00:00"); .set("date", "08:00:00");
@ -430,7 +430,7 @@ public class JSONObjectTest {
Assert.assertEquals("张三", jsonObject.getStr("name")); Assert.assertEquals("张三", jsonObject.getStr("name"));
Assert.assertEquals(new Integer(35), jsonObject.getInt("age")); Assert.assertEquals(new Integer(35), jsonObject.getInt("age"));
final JSONObject json = JSONUtil.createObj() final JSONObject json = JSONUtil.ofObj()
.set("name", "张三") .set("name", "张三")
.set("age", 35); .set("age", 35);
final BeanWithAlias bean = JSONUtil.toBean(Objects.requireNonNull(json).toString(), BeanWithAlias.class); final BeanWithAlias bean = JSONUtil.toBean(Objects.requireNonNull(json).toString(), BeanWithAlias.class);
@ -509,7 +509,7 @@ public class JSONObjectTest {
@Test @Test
public void getTimestampTest() { public void getTimestampTest() {
final String timeStr = "1970-01-01 00:00:00"; final String timeStr = "1970-01-01 00:00:00";
final JSONObject jsonObject = JSONUtil.createObj().set("time", timeStr); final JSONObject jsonObject = JSONUtil.ofObj().set("time", timeStr);
final Timestamp time = jsonObject.get("time", Timestamp.class); final Timestamp time = jsonObject.get("time", Timestamp.class);
Assert.assertEquals("1970-01-01 00:00:00.0", time.toString()); Assert.assertEquals("1970-01-01 00:00:00.0", time.toString());
} }
@ -616,7 +616,7 @@ public class JSONObjectTest {
@Test @Test
public void appendTest() { public void appendTest() {
final JSONObject jsonObject = JSONUtil.createObj().append("key1", "value1"); final JSONObject jsonObject = JSONUtil.ofObj().append("key1", "value1");
Assert.assertEquals("{\"key1\":\"value1\"}", jsonObject.toString()); Assert.assertEquals("{\"key1\":\"value1\"}", jsonObject.toString());
jsonObject.append("key1", "value2"); jsonObject.append("key1", "value2");
@ -649,7 +649,7 @@ public class JSONObjectTest {
@Test @Test
public void filterIncludeTest() { public void filterIncludeTest() {
final JSONObject json1 = JSONUtil.createObj(JSONConfig.of()) final JSONObject json1 = JSONUtil.ofObj(JSONConfig.of())
.set("a", "value1") .set("a", "value1")
.set("b", "value2") .set("b", "value2")
.set("c", "value3") .set("c", "value3")
@ -661,7 +661,7 @@ public class JSONObjectTest {
@Test @Test
public void filterExcludeTest() { public void filterExcludeTest() {
final JSONObject json1 = JSONUtil.createObj(JSONConfig.of()) final JSONObject json1 = JSONUtil.ofObj(JSONConfig.of())
.set("a", "value1") .set("a", "value1")
.set("b", "value2") .set("b", "value2")
.set("c", "value3") .set("c", "value3")
@ -673,7 +673,7 @@ public class JSONObjectTest {
@Test @Test
public void editTest() { public void editTest() {
final JSONObject json1 = JSONUtil.createObj(JSONConfig.of()) final JSONObject json1 = JSONUtil.ofObj(JSONConfig.of())
.set("a", "value1") .set("a", "value1")
.set("b", "value2") .set("b", "value2")
.set("c", "value3") .set("c", "value3")
@ -693,7 +693,7 @@ public class JSONObjectTest {
@Test @Test
public void toUnderLineCaseTest() { public void toUnderLineCaseTest() {
final JSONObject json1 = JSONUtil.createObj(JSONConfig.of()) final JSONObject json1 = JSONUtil.ofObj(JSONConfig.of())
.set("aKey", "value1") .set("aKey", "value1")
.set("bJob", "value2") .set("bJob", "value2")
.set("cGood", "value3") .set("cGood", "value3")
@ -708,7 +708,7 @@ public class JSONObjectTest {
@Test @Test
public void nullToEmptyTest() { public void nullToEmptyTest() {
final JSONObject json1 = JSONUtil.createObj(JSONConfig.of().setIgnoreNullValue(false)) final JSONObject json1 = JSONUtil.ofObj(JSONConfig.of().setIgnoreNullValue(false))
.set("a", null) .set("a", null)
.set("b", "value2"); .set("b", "value2");

View File

@ -177,7 +177,7 @@ public class JSONUtilTest {
@Test @Test
public void customValueTest() { public void customValueTest() {
final JSONObject jsonObject = JSONUtil.createObj() final JSONObject jsonObject = JSONUtil.ofObj()
.set("test2", (JSONString) () -> NumberUtil.format("#.0", 12.00D)); .set("test2", (JSONString) () -> NumberUtil.format("#.0", 12.00D));
Assert.assertEquals("{\"test2\":12.0}", jsonObject.toString()); Assert.assertEquals("{\"test2\":12.0}", jsonObject.toString());
@ -186,12 +186,12 @@ public class JSONUtilTest {
@Test @Test
public void setStripTrailingZerosTest() { public void setStripTrailingZerosTest() {
// 默认去除多余的0 // 默认去除多余的0
final JSONObject jsonObjectDefault = JSONUtil.createObj() final JSONObject jsonObjectDefault = JSONUtil.ofObj()
.set("test2", 12.00D); .set("test2", 12.00D);
Assert.assertEquals("{\"test2\":12}", jsonObjectDefault.toString()); Assert.assertEquals("{\"test2\":12}", jsonObjectDefault.toString());
// 不去除多余的0 // 不去除多余的0
final JSONObject jsonObject = JSONUtil.createObj(JSONConfig.of().setStripTrailingZeros(false)) final JSONObject jsonObject = JSONUtil.ofObj(JSONConfig.of().setStripTrailingZeros(false))
.set("test2", 12.00D); .set("test2", 12.00D);
Assert.assertEquals("{\"test2\":12.0}", jsonObject.toString()); Assert.assertEquals("{\"test2\":12.0}", jsonObject.toString());
@ -214,7 +214,7 @@ public class JSONUtilTest {
public void sqlExceptionTest(){ public void sqlExceptionTest(){
//https://github.com/dromara/hutool/issues/1399 //https://github.com/dromara/hutool/issues/1399
// SQLException实现了Iterable接口默认是遍历之会栈溢出修正后只返回string // SQLException实现了Iterable接口默认是遍历之会栈溢出修正后只返回string
final JSONObject set = JSONUtil.createObj().set("test", new SQLException("test")); final JSONObject set = JSONUtil.ofObj().set("test", new SQLException("test"));
Assert.assertEquals("{\"test\":\"java.sql.SQLException: test\"}", set.toString()); Assert.assertEquals("{\"test\":\"java.sql.SQLException: test\"}", set.toString());
} }
@ -227,7 +227,7 @@ public class JSONUtilTest {
@Test @Test
public void toXmlTest(){ public void toXmlTest(){
final JSONObject obj = JSONUtil.createObj(); final JSONObject obj = JSONUtil.ofObj();
obj.set("key1", "v1") obj.set("key1", "v1")
.set("key2", ListUtil.view("a", "b", "c")); .set("key2", ListUtil.view("a", "b", "c"));
final String xmlStr = JSONUtil.toXmlStr(obj); final String xmlStr = JSONUtil.toXmlStr(obj);

View File

@ -11,7 +11,7 @@ public class XMLTest {
@Test @Test
public void toXmlTest(){ public void toXmlTest(){
final JSONObject put = JSONUtil.createObj() final JSONObject put = JSONUtil.ofObj()
.set("aaa", "你好") .set("aaa", "你好")
.set("键2", "test"); .set("键2", "test");
final String s = JSONUtil.toXmlStr(put); final String s = JSONUtil.toXmlStr(put);
@ -31,7 +31,7 @@ public class XMLTest {
@Test @Test
public void xmlContentTest(){ public void xmlContentTest(){
final JSONObject jsonObject = JSONUtil.createObj().set("content","123456"); final JSONObject jsonObject = JSONUtil.ofObj().set("content","123456");
String xml = JSONXMLUtil.toXml(jsonObject); String xml = JSONXMLUtil.toXml(jsonObject);
Assert.assertEquals("123456", xml); Assert.assertEquals("123456", xml);