This commit is contained in:
Looly 2023-03-09 22:32:54 +08:00
parent 1a8a97e7b8
commit 0af9f4b5d8
16 changed files with 244 additions and 48 deletions

View File

@ -41,6 +41,12 @@
<version>${bouncycastle.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.24</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -17,7 +17,7 @@ import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.json.serialize.GlobalSerializeMapping;
import cn.hutool.json.serialize.JSONDeserializer;
import cn.hutool.json.serialize.JSONString;
import cn.hutool.json.serialize.JSONStringer;
import cn.hutool.json.writer.GlobalValueWriterMapping;
import cn.hutool.json.writer.JSONValueWriter;
@ -63,7 +63,7 @@ public final class InternalJSONUtil {
}
if (object instanceof JSON //
|| object instanceof JSONString //
|| object instanceof JSONStringer //
|| object instanceof CharSequence //
|| object instanceof Number //
|| ObjUtil.isBasicType(object) //
@ -117,8 +117,8 @@ public final class InternalJSONUtil {
/**
* 值转为String用于JSON中规则为
* <ul>
* <li>对象如果实现了{@link JSONString}接口调用{@link JSONString#toJSONString()}方法</li>
* <li>对象如果实现了{@link JSONString}接口调用{@link JSONString#toJSONString()}方法</li>
* <li>对象如果实现了{@link JSONStringer}接口调用{@link JSONStringer#toJSONString()}方法</li>
* <li>对象如果实现了{@link JSONStringer}接口调用{@link JSONStringer#toJSONString()}方法</li>
* <li>对象如果是数组或Collection包装为{@link JSONArray}</li>
* <li>对象如果是Map包装为{@link JSONObject}</li>
* <li>对象如果是数字使用{@link NumberUtil#toStr(Number)}转换为字符串</li>
@ -133,9 +133,9 @@ public final class InternalJSONUtil {
if (value == null) {
return StrUtil.NULL;
}
if (value instanceof JSONString) {
if (value instanceof JSONStringer) {
try {
return ((JSONString) value).toJSONString();
return ((JSONStringer) value).toJSONString();
} catch (final Exception e) {
throw new JSONException(e);
}

View File

@ -0,0 +1,81 @@
package cn.hutool.json;
import cn.hutool.core.lang.mutable.MutableEntry;
import cn.hutool.core.math.NumberUtil;
import java.io.IOException;
import java.io.Writer;
import java.util.function.Predicate;
/**
* JSON数字表示
*
* @author looly
* @since 6.0.0
*/
public class JSONNumber extends Number implements JSON {
private static final long serialVersionUID = 1L;
private final Number value;
/**
* 配置项
*/
private final JSONConfig config;
/**
* 构造
*
* @param value
* @param config JSON配置
*/
public JSONNumber(final Number value, final JSONConfig config) {
this.value = value;
this.config = config;
}
@Override
public JSONConfig getConfig() {
return this.config;
}
@Override
public int size() {
return 1;
}
@Override
public Writer write(final Writer writer, final int indentFactor, final int indent,
final Predicate<MutableEntry<Object, Object>> predicate) throws JSONException {
try {
writer.write(toString());
} catch (final IOException e) {
throw new RuntimeException(e);
}
return writer;
}
@Override
public int intValue() {
return this.value.intValue();
}
@Override
public long longValue() {
return this.value.longValue();
}
@Override
public float floatValue() {
return this.value.floatValue();
}
@Override
public double doubleValue() {
return this.value.doubleValue();
}
@Override
public String toString() {
return NumberUtil.toStr(this.value);
}
}

View File

@ -0,0 +1,76 @@
package cn.hutool.json;
import cn.hutool.core.lang.mutable.MutableEntry;
import java.io.IOException;
import java.io.Writer;
import java.util.function.Predicate;
/**
* JSON字符串表示一个字符串
*
* @author looly
* @since 6.0.0
*/
public class JSONString implements JSON, CharSequence {
private static final long serialVersionUID = 1L;
private final char[] value;
/**
* 配置项
*/
private final JSONConfig config;
/**
* 构造
*
* @param value char数组
* @param config 配置项
*/
public JSONString(final char[] value, final JSONConfig config) {
this.value = value;
this.config = config;
}
@Override
public JSONConfig getConfig() {
return this.config;
}
@Override
public int size() {
return length();
}
@Override
public Writer write(final Writer writer, final int indentFactor, final int indent,
final Predicate<MutableEntry<Object, Object>> predicate) throws JSONException {
try {
writer.write(this.value);
} catch (final IOException e) {
throw new RuntimeException(e);
}
return writer;
}
@Override
public int length() {
return this.value.length;
}
@Override
public char charAt(final int index) {
return this.value[index];
}
@Override
public CharSequence subSequence(final int start, final int end) {
return ((start == 0) && (end == this.value.length)) ? this
: new String(this.value, start, end);
}
@Override
public String toString() {
return String.valueOf(this.value);
}
}

View File

@ -2,7 +2,7 @@ package cn.hutool.json;
import cn.hutool.core.bean.copier.BeanCopier;
import cn.hutool.json.serialize.JSONDeserializer;
import cn.hutool.json.serialize.JSONString;
import cn.hutool.json.serialize.JSONStringer;
/**
* JSON支持<br>
@ -10,7 +10,7 @@ import cn.hutool.json.serialize.JSONString;
*
* @author Looly
*/
public class JSONSupport implements JSONString, JSONDeserializer<Object> {
public class JSONSupport implements JSONStringer, JSONDeserializer<Object> {
/**
* JSON String转Bean

View File

@ -12,20 +12,15 @@ import cn.hutool.core.convert.impl.DateConverter;
import cn.hutool.core.convert.impl.MapConverter;
import cn.hutool.core.convert.impl.TemporalAccessorConverter;
import cn.hutool.core.map.MapWrapper;
import cn.hutool.core.math.NumberUtil;
import cn.hutool.core.reflect.ConstructorUtil;
import cn.hutool.core.reflect.TypeReference;
import cn.hutool.core.reflect.TypeUtil;
import cn.hutool.core.text.StrUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.json.InternalJSONUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONException;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.json.*;
import cn.hutool.json.serialize.JSONDeserializer;
import cn.hutool.json.serialize.JSONString;
import cn.hutool.json.serialize.JSONStringer;
import java.lang.reflect.Type;
import java.time.temporal.TemporalAccessor;
@ -81,9 +76,9 @@ public class JSONConverter implements Converter {
if (null == value) {
return null;
}
if (value instanceof JSONString) {
if (value instanceof JSONStringer) {
// 被JSONString包装的对象获取其原始类型
value = ((JSONString) value).getRaw();
value = ((JSONStringer) value).getRaw();
}
// JSON转对象
@ -131,7 +126,20 @@ public class JSONConverter implements Converter {
json = (JSON) obj;
} else if (obj instanceof CharSequence) {
final String jsonStr = StrUtil.trim((CharSequence) obj);
json = JSONUtil.isTypeJSONArray(jsonStr) ? new JSONArray(jsonStr, config) : new JSONObject(jsonStr, config);
switch (jsonStr.charAt(0)){
case '"':
case '\'':
return new JSONString(jsonStr.toCharArray(), config);
case '[':
return new JSONArray(jsonStr, config);
case '{':
return new JSONObject(jsonStr, config);
default:
if(NumberUtil.isNumber(jsonStr)){
return new JSONNumber(NumberUtil.toBigDecimal(jsonStr), config);
}
throw new JSONException("Unsupported String to JSON: {}", jsonStr);
}
} else if (obj instanceof MapWrapper) {
// MapWrapper实现了Iterable会被当作JSONArray此处做修正
json = new JSONObject(obj, config);

View File

@ -20,7 +20,7 @@ import java.util.Date;
* @author looly
* @since 6.0.0
*/
public class DateJSONString implements JSONString {
public class DateJSONString implements JSONStringer {
final Object dateObj;
final JSONConfig jsonConfig;

View File

@ -10,7 +10,7 @@ import cn.hutool.core.lang.func.Wrapper;
*
*/
@FunctionalInterface
public interface JSONString extends Wrapper<Object> {
public interface JSONStringer extends Wrapper<Object> {
/**
* 自定义转JSON字符串的方法

View File

@ -1,7 +1,7 @@
package cn.hutool.json.writer;
import cn.hutool.json.JSONException;
import cn.hutool.json.serialize.JSONString;
import cn.hutool.json.serialize.JSONStringer;
import java.time.temporal.TemporalAccessor;
import java.util.Calendar;
@ -14,32 +14,32 @@ import java.util.Date;
* @author looly
* @since 6.0.0
*/
public class JSONStringValueWriter implements JSONValueWriter<JSONString> {
public class JSONStringValueWriter implements JSONValueWriter<JSONStringer> {
/**
* 单例对象
*/
public static final JSONStringValueWriter INSTANCE = new JSONStringValueWriter();
/**
* 输出实现了{@link JSONString}接口的对象通过调用{@link JSONString#toJSONString()}获取JSON字符串<br>
* {@link JSONString}按照JSON对象对待此方法输出的JSON字符串不包装引号<br>
* 输出实现了{@link JSONStringer}接口的对象通过调用{@link JSONStringer#toJSONString()}获取JSON字符串<br>
* {@link JSONStringer}按照JSON对象对待此方法输出的JSON字符串不包装引号<br>
* 如果toJSONString()返回null调用toString()方法并使用双引号包装
*
* @param writer {@link JSONWriter}
* @param jsonString {@link JSONString}
* @param jsonStringer {@link JSONStringer}
*/
@Override
public void write(final JSONWriter writer, final JSONString jsonString) {
public void write(final JSONWriter writer, final JSONStringer jsonStringer) {
final String valueStr;
try {
valueStr = jsonString.toJSONString();
valueStr = jsonStringer.toJSONString();
} catch (final Exception e) {
throw new JSONException(e);
}
if (null != valueStr) {
writer.writeRaw(valueStr);
} else {
writer.writeQuoteStrValue(jsonString.toString());
writer.writeQuoteStrValue(jsonStringer.toString());
}
}
}

View File

@ -8,7 +8,7 @@ import cn.hutool.core.util.ObjUtil;
import cn.hutool.json.InternalJSONUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.serialize.JSONString;
import cn.hutool.json.serialize.JSONStringer;
import java.io.IOException;
import java.io.Writer;
@ -321,8 +321,8 @@ public class JSONWriter extends Writer {
DateValueWriter.INSTANCE.write(this, value);
} else if (value instanceof Boolean) {
BooleanValueWriter.INSTANCE.write(this, (Boolean) value);
} else if (value instanceof JSONString) {
JSONStringValueWriter.INSTANCE.write(this, (JSONString) value);
} else if (value instanceof JSONStringer) {
JSONStringValueWriter.INSTANCE.write(this, (JSONStringer) value);
} else {
writeQuoteStrValue(value.toString());
}

View File

@ -0,0 +1,34 @@
package cn.hutool.json;
import org.junit.Assert;
import org.junit.Test;
public class IssueI6LBZATest {
@Test
public void parseJSONStringTest() {
final String a = "\"a\"";
final JSON parse = JSONUtil.parse(a);
Assert.assertEquals(JSONString.class, parse.getClass());
}
@Test
public void parseJSONStringTest2() {
final String a = "'a'";
final JSON parse = JSONUtil.parse(a);
Assert.assertEquals(JSONString.class, parse.getClass());
}
@Test(expected = JSONException.class)
public void parseJSONErrorTest() {
final String a = "a";
final JSON parse = JSONUtil.parse(a);
Assert.assertEquals(JSONString.class, parse.getClass());
}
@Test
public void parseJSONNumberTest() {
final String a = "123";
final JSON parse = JSONUtil.parse(a);
Assert.assertEquals(JSONNumber.class, parse.getClass());
}
}

View File

@ -4,7 +4,7 @@ import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.math.NumberUtil;
import cn.hutool.json.serialize.JSONString;
import cn.hutool.json.serialize.JSONStringer;
import cn.hutool.json.test.bean.Price;
import cn.hutool.json.test.bean.UserA;
import cn.hutool.json.test.bean.UserC;
@ -179,7 +179,7 @@ public class JSONUtilTest {
@Test
public void customValueTest() {
final JSONObject jsonObject = JSONUtil.ofObj()
.set("test2", (JSONString) () -> NumberUtil.format("#.0", 12.00D));
.set("test2", (JSONStringer) () -> NumberUtil.format("#.0", 12.00D));
Assert.assertEquals("{\"test2\":12.0}", jsonObject.toString());
}

View File

@ -1,7 +1,5 @@
package cn.hutool.log.test;
package cn.hutool.log;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import cn.hutool.log.dialect.commons.ApacheCommonsLogFactory;
import cn.hutool.log.dialect.console.ConsoleLogFactory;
import cn.hutool.log.dialect.jboss.JbossLogFactory;

View File

@ -1,12 +1,9 @@
package cn.hutool.log.test;
package cn.hutool.log;
import cn.hutool.log.level.Level;
import org.junit.Ignore;
import org.junit.Test;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import cn.hutool.log.level.Level;
/**
* 日志门面单元测试
* @author Looly

View File

@ -1,7 +1,5 @@
package cn.hutool.log.test;
package cn.hutool.log;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import cn.hutool.log.dialect.logtube.LogTubeLogFactory;
import org.junit.Test;

View File

@ -1,7 +1,5 @@
package cn.hutool.log.test;
package cn.hutool.log;
import cn.hutool.log.LogFactory;
import cn.hutool.log.StaticLog;
import cn.hutool.log.dialect.console.ConsoleColorLogFactory;
import cn.hutool.log.dialect.console.ConsoleLogFactory;
import org.junit.Test;