diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/BigNumberSerializer.java b/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/BigNumberSerializer.java new file mode 100644 index 0000000..732ef25 --- /dev/null +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/BigNumberSerializer.java @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2018-2099, DreamLu 卢春梦 (qq596392912@gmail.com). + *
+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *
+ * http://www.gnu.org/licenses/lgpl.html + *
+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springblade.core.tool.jackson; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; +import com.fasterxml.jackson.databind.ser.std.NumberSerializer; + +import java.io.IOException; + +/** + * 大数值序列化,避免超过js的精度,造成精度丢失 + * + * @author L.cm + */ +@JacksonStdImpl +public class BigNumberSerializer extends NumberSerializer { + + /** + * js 最大值为 Math.pow(2, 53),十进制为:9007199254740992 + */ + private static final long JS_NUM_MAX = 0x20000000000000L; + /** + * js 最小值为 -Math.pow(2, 53),十进制为:-9007199254740992 + */ + private static final long JS_NUM_MIN = -0x20000000000000L; + /** + * Static instance that is only to be used for {@link Number}. + */ + public final static BigNumberSerializer instance = new BigNumberSerializer(Number.class); + + public BigNumberSerializer(Class extends Number> rawType) { + super(rawType); + } + + @Override + public void serialize(Number value, JsonGenerator gen, SerializerProvider provider) throws IOException { + long longValue = value.longValue(); + if (longValue < JS_NUM_MIN || longValue > JS_NUM_MAX) { + gen.writeString(value.toString()); + } else { + super.serialize(value, gen, provider); + } + } +} diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/BladeJacksonProperties.java b/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/BladeJacksonProperties.java index 6759fb9..ea37749 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/BladeJacksonProperties.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/BladeJacksonProperties.java @@ -29,6 +29,15 @@ import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties("blade.jackson") public class BladeJacksonProperties { + /** + * null 转为 空,字符串转成"",数组转为[],对象转为{},数字转为-1 + */ + private Boolean nullToEmpty = Boolean.TRUE; + /** + * 响应到前端,大数值自动写出为 String,避免精度丢失 + */ + private Boolean bigNumToString = Boolean.TRUE; + /** * 支持 MediaType text/plain,用于和 blade-api-crypto 一起使用 */ diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/BladeNumberModule.java b/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/BladeNumberModule.java new file mode 100644 index 0000000..7e7eeed --- /dev/null +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/BladeNumberModule.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2018-2099, DreamLu 卢春梦 (qq596392912@gmail.com). + *
+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *
+ * http://www.gnu.org/licenses/lgpl.html + *
+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springblade.core.tool.jackson; + +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; + +import java.math.BigDecimal; +import java.math.BigInteger; + +/** + * 大整数序列化为 String 字符串,避免浏览器丢失精度 + * + *
+ * 前端建议采用: + * bignumber 库: https://github.com/MikeMcl/bignumber.js + * decimal.js 库: https://github.com/MikeMcl/decimal.js + *
+ * + * @author L.cm + */ +public class BladeNumberModule extends SimpleModule { + public static final BladeNumberModule INSTANCE = new BladeNumberModule(); + + public BladeNumberModule() { + super(BladeNumberModule.class.getName()); + // Long 和 BigInteger 采用定制的逻辑序列化,避免超过js的精度 + this.addSerializer(Long.class, BigNumberSerializer.instance); + this.addSerializer(Long.TYPE, BigNumberSerializer.instance); + this.addSerializer(BigInteger.class, BigNumberSerializer.instance); + // BigDecimal 采用 toString 避免精度丢失,前端采用 decimal.js 来计算。 + this.addSerializer(BigDecimal.class, ToStringSerializer.instance); + } +} diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/MappingApiJackson2HttpMessageConverter.java b/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/MappingApiJackson2HttpMessageConverter.java index b3a9b09..816e150 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/MappingApiJackson2HttpMessageConverter.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/MappingApiJackson2HttpMessageConverter.java @@ -49,7 +49,7 @@ public class MappingApiJackson2HttpMessageConverter extends AbstractReadWriteJac * @see Jackson2ObjectMapperBuilder#json() */ public MappingApiJackson2HttpMessageConverter(ObjectMapper objectMapper, BladeJacksonProperties properties) { - super(objectMapper, initWriteObjectMapper(objectMapper), initMediaType(properties)); + super(objectMapper, initWriteObjectMapper(objectMapper, properties), initMediaType(properties)); } private static List