Merge remote-tracking branch 'origin/v5-dev' into v5-dev

This commit is contained in:
bwcx_jzy 2023-09-07 09:14:43 +08:00
commit bd746c68eb
No known key found for this signature in database
GPG Key ID: E187D6E9DDDE8C53
23 changed files with 330 additions and 34 deletions

View File

@ -2,7 +2,7 @@
# 🚀Changelog # 🚀Changelog
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------
# 5.8.22(2023-08-16) # 5.8.22(2023-09-05)
### 🐣新特性 ### 🐣新特性
* 【core 】 NumberUtil.nullToZero增加重载issue#I7PPD2@Gitee * 【core 】 NumberUtil.nullToZero增加重载issue#I7PPD2@Gitee
@ -22,6 +22,15 @@
* 【core 】 去除默认的ACCEPT_LANGUAGEissue#3258@Github * 【core 】 去除默认的ACCEPT_LANGUAGEissue#3258@Github
* 【core 】 修复FieldsComparator比较结果不正确问题issue#3259@Github * 【core 】 修复FieldsComparator比较结果不正确问题issue#3259@Github
* 【core 】 修复Db.findAll全局忽略大小写无效问题issue#I7T30Y@Gitee * 【core 】 修复Db.findAll全局忽略大小写无效问题issue#I7T30Y@Gitee
* 【core 】 修复Ipv4Util.getEndIpLong 取反符号导致数据越界issue#I7U1OQ@Gitee
* 【http 】 修复302重定向时Location中的问号被转义问题issue#3265@Github
* 【core 】 修复CombinationAnnotationElement判断循环问题pr#3267@Github
* 【core 】 修复StrUtil#containsAny NPE问题pr#1063@Gitee
* 【all 】 修复SONArray的add()方法抛出OutOfMemory异常问题issue#3286@Github
* 【core 】 修复fillColumns空指针问题issue#3284@Github
* 【core 】 修复Convert不能转换Optional和Opt问题issue#I7WJHH@Gitee
* 【core 】 修复DateUtil.age年龄计算问题issue#I7XMYW@Gitee
* 【core 】 修复JSONUtil.parse()溢出问题issue#3289@Github
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------
# 5.8.21(2023-07-29) # 5.8.21(2023-07-29)

View File

@ -143,7 +143,7 @@ public class CombinationAnnotationElement implements AnnotatedElement, Serializa
annotationType = annotation.annotationType(); annotationType = annotation.annotationType();
// issue#I5FQGW@Gitee跳过元注解和已经处理过的注解防止递归调用 // issue#I5FQGW@Gitee跳过元注解和已经处理过的注解防止递归调用
if (AnnotationUtil.isNotJdkMateAnnotation(annotationType) if (AnnotationUtil.isNotJdkMateAnnotation(annotationType)
&& false == declaredAnnotationMap.containsKey(annotationType)) { && false == annotationMap.containsKey(annotationType)) {
if(test(annotation)){ if(test(annotation)){
annotationMap.put(annotationType, annotation); annotationMap.put(annotationType, annotation);
} }

View File

@ -2,8 +2,10 @@ package cn.hutool.core.collection;
import cn.hutool.core.comparator.PinyinComparator; import cn.hutool.core.comparator.PinyinComparator;
import cn.hutool.core.comparator.PropertyComparator; import cn.hutool.core.comparator.PropertyComparator;
import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Matcher; import cn.hutool.core.lang.Matcher;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.PageUtil; import cn.hutool.core.util.PageUtil;
@ -431,6 +433,8 @@ public class ListUtil {
if (index < size) { if (index < size) {
list.set(index, element); list.set(index, element);
} else { } else {
// issue#3286, 增加安全检查最多增加10倍
Validator.checkIndexLimit(index, list.size());
for (int i = size; i < index; i++) { for (int i = size; i < index; i++) {
list.add(paddingElement); list.add(paddingElement);
} }

View File

@ -193,6 +193,20 @@ public class ConverterRegistry implements Serializable {
type = defaultValue.getClass(); type = defaultValue.getClass();
} }
// issue#I7WJHHOpt和Optional处理
if (value instanceof Opt) {
value = ((Opt<T>) value).get();
if (ObjUtil.isNull(value)) {
return defaultValue;
}
}
if (value instanceof Optional) {
value = ((Optional<T>) value).orElse(null);
if (ObjUtil.isNull(value)) {
return defaultValue;
}
}
if (type instanceof TypeReference) { if (type instanceof TypeReference) {
type = ((TypeReference<?>) type).getType(); type = ((TypeReference<?>) type).getType();
} }

View File

@ -629,7 +629,12 @@ public class CalendarUtil {
} }
/** /**
* 计算相对于dateToCompare的年龄常用于计算指定生日在某年的年龄 * 计算相对于dateToCompare的年龄常用于计算指定生日在某年的年龄<br>
* 按照最高人民法院关于审理未成年人刑事案件具体应用法律若干问题的解释第二条规定刑法第十七条规定的周岁按照公历的年日计算从周岁生日的第二天起算
* <ul>
* <li>2022-03-01出生则相对2023-03-01周岁为0相对于2023-03-02才是1岁</li>
* <li>1999-02-28出生则相对2000-02-29周岁为1</li>
* </ul>
* *
* @param birthday 生日 * @param birthday 生日
* @param dateToCompare 需要对比的日期 * @param dateToCompare 需要对比的日期
@ -646,22 +651,22 @@ public class CalendarUtil {
final int year = cal.get(Calendar.YEAR); final int year = cal.get(Calendar.YEAR);
final int month = cal.get(Calendar.MONTH); final int month = cal.get(Calendar.MONTH);
final int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH); final int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
final boolean isLastDayOfMonth = dayOfMonth == cal.getActualMaximum(Calendar.DAY_OF_MONTH);
// 复用cal
cal.setTimeInMillis(birthday); cal.setTimeInMillis(birthday);
int age = year - cal.get(Calendar.YEAR); int age = year - cal.get(Calendar.YEAR);
final int monthBirth = cal.get(Calendar.MONTH);
//当前日期则为0岁 //当前日期则为0岁
if (age == 0){ if (age == 0){
return 0; return 0;
} else if (month == monthBirth) { }
final int monthBirth = cal.get(Calendar.MONTH);
if (month == monthBirth) {
final int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH); final int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
final boolean isLastDayOfMonthBirth = dayOfMonthBirth == cal.getActualMaximum(Calendar.DAY_OF_MONTH); // issue#I6E6ZG法定生日当天不算年龄从第二天开始计算
if ((false == isLastDayOfMonth || false == isLastDayOfMonthBirth) && dayOfMonth <= dayOfMonthBirth) { if (dayOfMonth <= dayOfMonthBirth) {
// 如果生日在当月但是未超过生日当天的日期年龄减一 // 如果生日在当月但是未达到生日当天的日期年龄减一
age--; age--;
} }
} else if (month < monthBirth) { } else if (month < monthBirth) {

View File

@ -97,7 +97,7 @@ public class ConsoleTable {
*/ */
private void fillColumns(List<String> l, String[] columns) { private void fillColumns(List<String> l, String[] columns) {
for (int i = 0; i < columns.length; i++) { for (int i = 0; i < columns.length; i++) {
String column = columns[i]; String column = StrUtil.toString(columns[i]);
if (isSBCMode) { if (isSBCMode) {
column = Convert.toSBC(column); column = Convert.toSBC(column);
} }

View File

@ -1257,4 +1257,23 @@ public class Validator {
} }
return value; return value;
} }
/**
* 检查给定的index是否超出长度限制默认检查超出倍数10倍此方法主要用于内部检查包括
* <ul>
* <li>数组调用setOrPadding时最多允许padding的长度</li>
* <li>List调用setOrPadding时最多允许padding的长度</li>
* <li>JSONArray调用setOrPadding时最多允许padding的长度</li>
* </ul>
*
* @param index 索引
* @param size 数组列表长度
* @since 5.8.22
*/
public static void checkIndexLimit(final int index, final int size) {
// issue#3286, 增加安全检查最多增加10倍
if (index > (size + 1) * 10) {
throw new ValidateException("Index [{}] is too large for size: [{}]", index, size);
}
}
} }

View File

@ -407,7 +407,7 @@ public class Ipv4Util {
*/ */
public static Long getEndIpLong(String ip, int maskBit) { public static Long getEndIpLong(String ip, int maskBit) {
return getBeginIpLong(ip, maskBit) return getBeginIpLong(ip, maskBit)
+ ~ipv4ToLong(getMaskByMaskBit(maskBit)); + (0xffffffffL & ~ipv4ToLong(getMaskByMaskBit(maskBit)));
} }
/** /**

View File

@ -1064,7 +1064,7 @@ public class CharSequenceUtil {
return null; return null;
} }
for (CharSequence checkStr : testStrs) { for (CharSequence checkStr : testStrs) {
if (str.toString().contains(checkStr)) { if (null != checkStr && str.toString().contains(checkStr)) {
return checkStr.toString(); return checkStr.toString();
} }
} }

View File

@ -2948,10 +2948,10 @@ public class NumberUtil {
/** /**
* 检查是否为有效的数字<br> * 检查是否为有效的数字<br>
* 检查Double和Float是否为无限大或者Not a Number<br> * 检查Double和Float是否为无限大或者Not a Number<br>
* 非数字类型和Null将返回true * 非数字类型和Null将返回false
* *
* @param number 被检查类型 * @param number 被检查类型
* @return 检查结果非数字类型和Null将返回true * @return 检查结果非数字类型和Null将返回false
* @since 4.6.7 * @since 4.6.7
*/ */
public static boolean isValidNumber(Number number) { public static boolean isValidNumber(Number number) {

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package cn.hutool.core.convert;
import cn.hutool.core.lang.Opt;
import org.junit.Assert;
import org.junit.Test;
import java.util.Optional;
public class IssueI7WJHHTest {
@Test
public void toIntTest() {
final Optional<Integer> optional = Optional.of(1);
final Integer integer = Convert.toInt(optional);
Assert.assertEquals(Integer.valueOf(1), integer);
}
@Test
public void toIntTest2() {
final Opt<Integer> optional = Opt.of(1);
final Integer integer = Convert.toInt(optional);
Assert.assertEquals(Integer.valueOf(1), integer);
}
}

View File

@ -868,7 +868,9 @@ public class DateUtilTest {
final String d1 = "2000-02-29"; final String d1 = "2000-02-29";
final String d2 = "2018-02-28"; final String d2 = "2018-02-28";
final int age = DateUtil.age(DateUtil.parseDate(d1), DateUtil.parseDate(d2)); final int age = DateUtil.age(DateUtil.parseDate(d1), DateUtil.parseDate(d2));
Assert.assertEquals(18, age);
// issue#I6E6ZG法定生日当天不算年龄从第二天开始计算
Assert.assertEquals(17, age);
} }
@Test(expected = IllegalArgumentException.class) @Test(expected = IllegalArgumentException.class)
@ -878,6 +880,28 @@ public class DateUtilTest {
DateUtil.age(DateUtil.parseDate(d1), DateUtil.parseDate(d2)); DateUtil.age(DateUtil.parseDate(d1), DateUtil.parseDate(d2));
} }
@Test
public void ageTest3() {
// 按照最高人民法院关于审理未成年人刑事案件具体应用法律若干问题的解释第二条规定刑法第十七条规定的周岁按照公历的年日计算从周岁生日的第二天起算
// 那我们认为就算当年是闰年29日也算周岁生日的第二天可以算作一岁
final String d1 = "1998-02-28";
final String d2 = "2000-02-29";
final int age = DateUtil.age(DateUtil.parse(d1), DateUtil.parse(d2));
// issue#I6E6ZG法定生日当天不算年龄从第二天开始计算
Assert.assertEquals(2, age);
}
@Test
public void ageTest4() {
// 按照最高人民法院关于审理未成年人刑事案件具体应用法律若干问题的解释第二条规定刑法第十七条规定的周岁按照公历的年日计算从周岁生日的第二天起算
// 那我们认为就算当年是闰年29日也算周岁生日的第二天可以算作一岁
final String d1 = "1999-02-28";
final String d2 = "2000-02-29";
final int age = DateUtil.age(DateUtil.parse(d1), DateUtil.parse(d2));
// issue#I6E6ZG法定生日当天不算年龄从第二天开始计算
Assert.assertEquals(1, age);
}
@Test @Test
public void isExpiredTest() { public void isExpiredTest() {
final DateTime startDate = DateUtil.parse("2019-12-01 17:02:30"); final DateTime startDate = DateUtil.parse("2019-12-01 17:02:30");

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package cn.hutool.core.date;
import org.junit.Assert;
import org.junit.Test;
public class IssueI7XMYWTest {
@Test
public void ageTest() {
DateTime date1 = DateUtil.parse("2023-08-31");
Assert.assertEquals(49, DateUtil.age(DateUtil.parse("1973-08-31"), date1));
date1 = DateUtil.parse("2023-08-30");
Assert.assertEquals(49, DateUtil.age(DateUtil.parse("1973-08-30"), date1));
}
}

View File

@ -220,6 +220,12 @@ public class NumberUtilTest {
Assert.assertEquals("467.81", format); Assert.assertEquals("467.81", format);
} }
@Test
public void isValidNumberTest() {
boolean validNumber = NumberUtil.isValidNumber(1);
Assert.assertTrue(validNumber);
}
@Test @Test
public void decimalFormatMoneyTest() { public void decimalFormatMoneyTest() {
final double c = 299792400.543534534; final double c = 299792400.543534534;

View File

@ -412,6 +412,10 @@ public class StrUtilTest {
Assert.assertFalse(containsAny); Assert.assertFalse(containsAny);
containsAny = StrUtil.containsAny("aaabbbccc", "d", "c"); containsAny = StrUtil.containsAny("aaabbbccc", "d", "c");
Assert.assertTrue(containsAny); Assert.assertTrue(containsAny);
// https://gitee.com/dromara/hutool/issues/I7WSYD
containsAny = StrUtil.containsAny("你好啊", "", null);
Assert.assertFalse(containsAny);
} }
@Test @Test

View File

@ -130,7 +130,8 @@ public class PartParser {
if (size == 1) {// 普通形式 if (size == 1) {// 普通形式
results = parseRange(value, -1); results = parseRange(value, -1);
} else if (size == 2) {// 间隔形式 } else if (size == 2) {// 间隔形式
final int step = parseNumber(parts.get(1)); // issue#I7SMP7步进不检查范围
final int step = parseNumber(parts.get(1), false);
if (step < 1) { if (step < 1) {
throw new CronException("Non positive divisor for field: [{}]", value); throw new CronException("Non positive divisor for field: [{}]", value);
} }
@ -163,7 +164,7 @@ public class PartParser {
//根据步进的第一个数字确定起始时间类似于 12/3则从12分等开始 //根据步进的第一个数字确定起始时间类似于 12/3则从12分等开始
int minValue = part.getMin(); int minValue = part.getMin();
if (false == isMatchAllStr(value)) { if (false == isMatchAllStr(value)) {
minValue = Math.max(minValue, parseNumber(value)); minValue = Math.max(minValue, parseNumber(value, true));
} else { } else {
//在全匹配模式下如果步进不存在表示步进为1 //在全匹配模式下如果步进不存在表示步进为1
if (step < 1) { if (step < 1) {
@ -190,15 +191,15 @@ public class PartParser {
List<String> parts = StrUtil.split(value, '-'); List<String> parts = StrUtil.split(value, '-');
int size = parts.size(); int size = parts.size();
if (size == 1) {// 普通值 if (size == 1) {// 普通值
final int v1 = parseNumber(value); final int v1 = parseNumber(value, true);
if (step > 0) {//类似 20/2的形式 if (step > 0) {//类似 20/2的形式
NumberUtil.appendRange(v1, part.getMax(), step, results); NumberUtil.appendRange(v1, part.getMax(), step, results);
} else { } else {
results.add(v1); results.add(v1);
} }
} else if (size == 2) {// range值 } else if (size == 2) {// range值
final int v1 = parseNumber(parts.get(0)); final int v1 = parseNumber(parts.get(0), true);
final int v2 = parseNumber(parts.get(1)); final int v2 = parseNumber(parts.get(1), true);
if (step < 1) { if (step < 1) {
//在range模式下如果步进不存在表示步进为1 //在range模式下如果步进不存在表示步进为1
step = 1; step = 1;
@ -233,10 +234,11 @@ public class PartParser {
* 解析单个int值支持别名 * 解析单个int值支持别名
* *
* @param value 被解析的值 * @param value 被解析的值
* @param checkValue 是否检查值在有效范围内
* @return 解析结果 * @return 解析结果
* @throws CronException 当无效数字或无效别名时抛出 * @throws CronException 当无效数字或无效别名时抛出
*/ */
private int parseNumber(String value) throws CronException { private int parseNumber(String value, boolean checkValue) throws CronException {
int i; int i;
try { try {
i = Integer.parseInt(value); i = Integer.parseInt(value);
@ -254,13 +256,7 @@ public class PartParser {
i = Week.SUNDAY.ordinal(); i = Week.SUNDAY.ordinal();
} }
// issue#I7SMP7 return checkValue ? part.checkValue(i) : i;
// 年的形式中如果类似于*/2不做范围检查
if(Part.YEAR.equals(this.part)){
return i;
}
return part.checkValue(i);
} }
/** /**

View File

@ -1293,13 +1293,23 @@ public class HttpRequest extends HttpBase<HttpRequest> {
final UrlBuilder redirectUrl; final UrlBuilder redirectUrl;
String location = httpConnection.header(Header.LOCATION); String location = httpConnection.header(Header.LOCATION);
if (false == HttpUtil.isHttp(location) && false == HttpUtil.isHttps(location)) { if (false == HttpUtil.isHttp(location) && false == HttpUtil.isHttps(location)) {
// issue#I5TPSY // issue#I5TPSY, location可能为相对路径
// location可能为相对路径
if (false == location.startsWith("/")) { if (false == location.startsWith("/")) {
location = StrUtil.addSuffixIfNot(this.url.getPathStr(), "/") + location; location = StrUtil.addSuffixIfNot(this.url.getPathStr(), "/") + location;
} }
// issue#3265, 相对路径中可能存在参数单独处理参数
final String query;
final List<String> split = StrUtil.split(location, '?', 2);
if (split.size() == 2) {
// 存在参数
location = split.get(0);
query = split.get(1);
} else {
query = null;
}
redirectUrl = UrlBuilder.of(this.url.getScheme(), this.url.getHost(), this.url.getPort() redirectUrl = UrlBuilder.of(this.url.getScheme(), this.url.getHost(), this.url.getPort()
, location, null, null, this.charset); , location, query, null, this.charset);
} else { } else {
redirectUrl = UrlBuilder.ofHttpWithoutEncode(location); redirectUrl = UrlBuilder.ofHttpWithoutEncode(location);
} }

View File

@ -0,0 +1,24 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package cn.hutool.http;
import cn.hutool.core.lang.Console;
import org.junit.Test;
public class IssueI7WZEOTest {
@Test
public void postTest() {
final String post = HttpUtil.post("https://tenapi.cn/v2/video", "url=https://v.douyin.com/ie1EX3LH/");
Console.log(post);
}
}

View File

@ -3,6 +3,7 @@ package cn.hutool.json;
import cn.hutool.core.bean.BeanPath; import cn.hutool.core.bean.BeanPath;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Filter; import cn.hutool.core.lang.Filter;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.lang.mutable.Mutable; import cn.hutool.core.lang.mutable.Mutable;
import cn.hutool.core.lang.mutable.MutableObj; import cn.hutool.core.lang.mutable.MutableObj;
import cn.hutool.core.lang.mutable.MutablePair; import cn.hutool.core.lang.mutable.MutablePair;
@ -457,6 +458,8 @@ public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, Rando
InternalJSONUtil.testValidity(element); InternalJSONUtil.testValidity(element);
this.rawList.add(index, JSONUtil.wrap(element, this.config)); this.rawList.add(index, JSONUtil.wrap(element, this.config));
} else { } else {
// issue#3286, 增加安全检查最多增加10倍
Validator.checkIndexLimit(index, this.size());
while (index != this.size()) { while (index != this.size()) {
this.add(JSONNull.NULL); this.add(JSONNull.NULL);
} }

View File

@ -1,5 +1,6 @@
package cn.hutool.json; package cn.hutool.json;
import cn.hutool.core.lang.Console;
import cn.hutool.core.lang.Filter; import cn.hutool.core.lang.Filter;
import cn.hutool.core.lang.mutable.Mutable; import cn.hutool.core.lang.mutable.Mutable;
import cn.hutool.core.lang.mutable.MutablePair; import cn.hutool.core.lang.mutable.MutablePair;
@ -66,7 +67,7 @@ public class JSONParser {
} }
default: default:
tokener.back(); tokener.back();
key = tokener.nextValue().toString(); key = tokener.nextStringValue();
} }
// The key is followed by ':'. // The key is followed by ':'.

View File

@ -322,6 +322,43 @@ public class JSONTokener {
} }
} }
/**
* 获取下一个String格式的值用户获取key
* @return String格式的值
* @since 5.8.22
*/
public String nextStringValue(){
char c = this.nextClean();
switch (c) {
case '"':
case '\'':
return this.nextString(c);
case '{':
case '[':
throw this.syntaxError("Sting value must be not begin with a '{' or '['");
}
/*
* Handle unquoted text. This could be the values true, false, or null, or it can be a number.
* An implementation (such as this one) is allowed to also accept non-standard forms. Accumulate
* characters until we reach the end of the text or a formatting character.
*/
final StringBuilder sb = new StringBuilder();
while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) {
sb.append(c);
c = this.next();
}
this.back();
final String string = sb.toString().trim();
if (string.isEmpty()) {
throw this.syntaxError("Missing value");
}
return string;
}
/** /**
* 获得下一个值值类型可以是Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the JSONObject.NULL * 获得下一个值值类型可以是Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the JSONObject.NULL
* *
@ -366,7 +403,7 @@ public class JSONTokener {
this.back(); this.back();
string = sb.toString().trim(); string = sb.toString().trim();
if (0 == string.length()) { if (string.isEmpty()) {
throw this.syntaxError("Missing value"); throw this.syntaxError("Missing value");
} }
return InternalJSONUtil.stringToValue(string); return InternalJSONUtil.stringToValue(string);

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package cn.hutool.json;
import lombok.Data;
import lombok.Getter;
import org.junit.Assert;
import org.junit.Test;
public class Issue3274Test {
@Test
public void toBeanTest(){
final JSONObject entries = new JSONObject("{\n" +
" \n" +
" \"age\": 36,\n" +
" \"gender\": \"\",\n" +
" \"id\": \"123123123\"\n" +
"}", JSONConfig.create().setIgnoreError(true));
final LarkCoreHrPersonal larkCoreHrPersonal = entries.toBean(LarkCoreHrPersonal.class);
Assert.assertNotNull(larkCoreHrPersonal);
}
@Data
static class LarkCoreHrPersonal {
private String id;
private String age="";
private Gender gender;
}
@Getter
enum Gender {
male("male","Male",""),
female("female","Female",""),
other("other","Other","其他");
private JSONArray display;
private String enum_name;
Gender(final String enum_name, final String en_Us, final String zh_CN){
this.enum_name=enum_name;
this.display=new JSONArray("[{\"lang\": \"en-US\",\"value\": \""+en_Us+"\"},{\"lang\": \"zh-CN\",\"value\": \""+zh_CN+"\"}]");
}
}
}

View File

@ -0,0 +1,23 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package cn.hutool.json;
import org.junit.Test;
public class Issue3289Test {
@Test(expected = JSONException.class)
public void parseTest() {
final String s = "{\"a\":1,[6E962756779]}";
JSONUtil.parse(s);
}
}