增加JSONConfig.setNumberWriteMode

This commit is contained in:
Looly 2024-04-11 22:36:47 +08:00
parent b859cf4913
commit 3f7f05b9ee
4 changed files with 150 additions and 2 deletions

View File

@ -15,6 +15,7 @@ package org.dromara.hutool.json;
import org.dromara.hutool.core.comparator.CompareUtil;
import org.dromara.hutool.core.convert.Converter;
import org.dromara.hutool.json.convert.JSONConverter;
import org.dromara.hutool.json.writer.NumberWriteMode;
import java.io.Serializable;
import java.util.Comparator;
@ -64,6 +65,10 @@ public class JSONConfig implements Serializable {
* 自定义的类型转换器用于在getXXX操作中自动转换类型
*/
private Converter converter = JSONConverter.of(this);
/**
* Number写出模式
*/
private NumberWriteMode numberWriteMode = NumberWriteMode.NORMAL;
/**
* 创建默认的配置项
@ -257,6 +262,7 @@ public class JSONConfig implements Serializable {
/**
* 获取自定义的类型转换器用于在序列化反序列化操作中实现对象类型转换
*
* @return 转换器
*/
public Converter getConverter() {
@ -265,9 +271,33 @@ public class JSONConfig implements Serializable {
/**
* 设置自定义的类型转换器用于在序列化反序列化操作中实现对象类型转换
*
* @param converter 转换器
*/
public void setConverter(final Converter converter) {
this.converter = converter;
}
/**
* 获取Number写出模式
*
* @return Number写出模式
* @since 6.0.0
*/
public NumberWriteMode getNumberWriteMode() {
return numberWriteMode;
}
/**
* 设置数字写出模式<br>
* 考虑到在JS或其他环境中Number超过一定长度会丢失精度因此针对Number类型值可选写出规则
*
* @param numberWriteMode Number写出模式
* @return this
* @since 6.0.0
*/
public JSONConfig setNumberWriteMode(final NumberWriteMode numberWriteMode) {
this.numberWriteMode = numberWriteMode;
return this;
}
}

View File

@ -22,6 +22,12 @@ import org.dromara.hutool.json.JSONConfig;
* @since 6.0.0
*/
public class NumberValueWriter implements JSONValueWriter<Number> {
/**
* JS中表示的数字最大值
*/
private static final long JS_MAX_NUMBER = 9007199254740992L;
/**
* 单例对象
*/
@ -39,7 +45,24 @@ public class NumberValueWriter implements JSONValueWriter<Number> {
public void write(final JSONWriter writer, final Number number) {
final JSONConfig config = writer.getConfig();
// since 5.6.2可配置是否去除末尾多余0例如如果为true,5.0返回5
final boolean isStripTrailingZeros = null == config || config.isStripTrailingZeros();
writer.writeRaw(NumberUtil.toStr(number, isStripTrailingZeros));
final boolean isStripTrailingZeros = (null == config) || config.isStripTrailingZeros();
final String numberStr = NumberUtil.toStr(number, isStripTrailingZeros);
final NumberWriteMode numberWriteMode = (null == config) ? NumberWriteMode.NORMAL : config.getNumberWriteMode();
switch (numberWriteMode){
case JS:
if(number.longValue() > JS_MAX_NUMBER){
writer.writeQuoteStrValue(numberStr);
} else{
writer.writeRaw(numberStr);
}
break;
case STRING:
writer.writeQuoteStrValue(numberStr);
break;
default:
writer.writeRaw(numberStr);
break;
}
}
}

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2024. 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:
* https://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 org.dromara.hutool.json.writer;
/**
* Long写出模式<br>
* 考虑到在JS或其他环境中Long超过一定长度会丢失精度因此针对Long类型值可选写出规则
*
* @author Looly
* @since 6.0.0
*/
public enum NumberWriteMode {
/**
* 一般模式所有Long值写出为普通数字{"value": 123456789}
*/
NORMAL,
/**
* 浏览器中Javascript兼容模式此模式下如果Long输出长度大于
*/
JS,
/**
* 所有Long类型的数字均转为字符串形式{"value": "123456789"}
*/
STRING
}

View File

@ -0,0 +1,60 @@
package org.dromara.hutool.json.writer;
import lombok.Data;
import org.dromara.hutool.json.JSONConfig;
import org.dromara.hutool.json.JSONUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
public class Issue3541Test {
@Test
void writeNumberJSTest() {
final Demo demo = new Demo();
// 超出长度
demo.setId(1227690722069581409L);
demo.setName("hutool");
final String jsonStr = JSONUtil.toJsonStr(demo, JSONConfig.of().setNumberWriteMode(NumberWriteMode.JS));
Assertions.assertEquals("{\"id\":\"1227690722069581409\",\"name\":\"hutool\"}", jsonStr);
// 未超出长度
demo.setId(1227690722069581L);
final String jsonStr2 = JSONUtil.toJsonStr(demo, JSONConfig.of().setNumberWriteMode(NumberWriteMode.JS));
Assertions.assertEquals("{\"id\":1227690722069581,\"name\":\"hutool\"}", jsonStr2);
}
@Test
void writeNumberStringTest() {
final Demo demo = new Demo();
// 超出长度
demo.setId(1227690722069581409L);
demo.setName("hutool");
final String jsonStr = JSONUtil.toJsonStr(demo, JSONConfig.of().setNumberWriteMode(NumberWriteMode.STRING));
Assertions.assertEquals("{\"id\":\"1227690722069581409\",\"name\":\"hutool\"}", jsonStr);
// 未超出长度
demo.setId(1227690722069581L);
final String jsonStr2 = JSONUtil.toJsonStr(demo, JSONConfig.of().setNumberWriteMode(NumberWriteMode.STRING));
Assertions.assertEquals("{\"id\":\"1227690722069581\",\"name\":\"hutool\"}", jsonStr2);
}
@Test
void writeNumberNormalTest() {
final Demo demo = new Demo();
// 超出长度
demo.setId(1227690722069581409L);
demo.setName("hutool");
final String jsonStr = JSONUtil.toJsonStr(demo, JSONConfig.of().setNumberWriteMode(NumberWriteMode.NORMAL));
Assertions.assertEquals("{\"id\":1227690722069581409,\"name\":\"hutool\"}", jsonStr);
// 未超出长度
demo.setId(1227690722069581L);
final String jsonStr2 = JSONUtil.toJsonStr(demo, JSONConfig.of().setNumberWriteMode(NumberWriteMode.NORMAL));
Assertions.assertEquals("{\"id\":1227690722069581,\"name\":\"hutool\"}", jsonStr2);
}
@Data
public static class Demo {
private Long id;
private String name;
}
}