Repository: alibaba/fastjson2
Pull request #3136 (2024-10-26 07:32:33)

When using BrowserCompatible, BigDecimal in the Double range behaves the same as Double. for issue #3123
### What this PR does / why we need it?

### Summary of your change
```java
public static boolean isJavaScriptSupport(BigDecimal decimal) {
        boolean jsSupport = decimal.precision() < 16 || isJavaScriptSupport(decimal.unscaledValue());
        if (!jsSupport && decimal.scale() != 0) {
            //Use double for comparison
            //double and javascript number have the same precision
            //In extreme cases, precision loss may occur.
            //There will be a loss of precision between [4.9e-324, 5e-324), which will be converted to 5e-324 by JavaScript.
            //This situation can be ignored
            double doubleValue;
            try {
                doubleValue = decimal.doubleValue();
            } catch (Exception ex) {
                return false;
            }
            jsSupport = decimal.compareTo(BigDecimal.valueOf(doubleValue)) == 0;
        }
        return jsSupport;
    }
```
#### Please indicate you've done the following:

- [x] Made sure tests are passing and test coverage is added if needed.
- [x] Made sure commit message follow the rule of [Conventional Commits specification](https://www.conventionalcommits.org/).
- [x] Considered the docs impact and opened a new docs issue or PR with docs changes if needed.


wenshao: 这个没解决Double输出的问题吧
rowstop: > 这个没解决Double输出的问题吧

double 和 javascript 的 Number 范围相似，只有在±[4.9e-324, 5e-324)范围内会被转为±5e-324，这种情况可以忽略了
rowstop: 
![image](https://github.com/user-attachments/assets/cbabe9e0-b4cf-429e-b9e8-4bc286fda031)

![image](https://github.com/user-attachments/assets/5d1e003f-818a-4efd-b10d-312d1be6c664)
wenshao: 很抱歉，让你等太久了，可以修复下冲突么？
rowstop: down
rowstop: > 很抱歉，让你等太久了，可以修复下冲突么？

没事的😄
rowstop: done

Patch:
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java
index a52167951..2cb955958 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java
@@ -823,7 +823,7 @@ public abstract class JSONWriter
 
     protected static boolean isWriteAsString(BigDecimal value, long features) {
         return (features & MASK_WRITE_NON_STRING_VALUE_AS_STRING) != 0
-                || ((features & MASK_BROWSER_COMPATIBLE) != 0 && value.precision() >= 16 && !isJavaScriptSupport(value.unscaledValue()));
+                || ((features & MASK_BROWSER_COMPATIBLE) != 0 && !isJavaScriptSupport(value));
     }
 
     public abstract void writeNameRaw(char[] chars);
diff --git a/core/src/main/java/com/alibaba/fastjson2/util/TypeUtils.java b/core/src/main/java/com/alibaba/fastjson2/util/TypeUtils.java
index 84528d078..b6fadd5f9 100644
--- a/core/src/main/java/com/alibaba/fastjson2/util/TypeUtils.java
+++ b/core/src/main/java/com/alibaba/fastjson2/util/TypeUtils.java
@@ -3755,8 +3755,23 @@ public class TypeUtils {
         return i >= LONG_JAVASCRIPT_LOW && i <= LONG_JAVASCRIPT_HIGH;
     }
 
-    public static boolean isJavaScriptSupport(BigDecimal i) {
-        return i.precision() >= 16 && isJavaScriptSupport(i.unscaledValue());
+    public static boolean isJavaScriptSupport(BigDecimal decimal) {
+        boolean jsSupport = decimal.precision() < 16 || isJavaScriptSupport(decimal.unscaledValue());
+        if (!jsSupport && decimal.scale() != 0) {
+            //Use double for comparison
+            //double and javascript number have the same precision
+            //In extreme cases, precision loss may occur.
+            //There will be a loss of precision between [4.9e-324, 5e-324), which will be converted to 5e-324 by JavaScript.
+            //This situation can be ignored
+            double doubleValue;
+            try {
+                doubleValue = decimal.doubleValue();
+            } catch (Exception ex) {
+                return false;
+            }
+            jsSupport = decimal.compareTo(BigDecimal.valueOf(doubleValue)) == 0;
+        }
+        return jsSupport;
     }
 
     public static boolean isJavaScriptSupport(BigInteger i) {


Test patch:
diff --git a/core/src/test/java/com/alibaba/fastjson2/issues_3100/Issue3123.java b/core/src/test/java/com/alibaba/fastjson2/issues_3100/Issue3123.java
new file mode 100644
index 000000000..e1790ec75
--- /dev/null
+++ b/core/src/test/java/com/alibaba/fastjson2/issues_3100/Issue3123.java
@@ -0,0 +1,44 @@
+package com.alibaba.fastjson2.issues_3100;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONWriter;
+import lombok.SneakyThrows;
+import org.junit.jupiter.api.Test;
+import org.skyscreamer.jsonassert.JSONAssert;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author 张治保
+ * @since 2024/10/22
+ */
+public class Issue3123 {
+    @Test
+    @SneakyThrows
+    void test() {
+        BigDecimal num1 = BigDecimal.valueOf(107.29305145106407);
+        BigDecimal num2 = BigDecimal.valueOf(23.42835970945431);
+        BigDecimal num3 = BigDecimal.valueOf(23.427479896686418);
+
+        Double num11 = 107.29305145106407;
+        Double num21 = 23.42835970945431;
+        Double num31 = 23.427479896686418;
+
+        Map map = new HashMap<>();
+        map.put("b1", num1);
+        map.put("b2", num2);
+        map.put("b3", num3);
+
+        map.put("d1", num11);
+        map.put("d2", num21);
+        map.put("d3", num31);
+
+        JSONAssert.assertEquals(
+                "{\"b1\":107.29305145106407,\"b2\":23.42835970945431,\"b3\":23.427479896686418,\"d1\":107.29305145106407,\"d2\":23.42835970945431,\"d3\":23.427479896686418}",
+                JSON.toJSONString(map, JSONWriter.Feature.BrowserCompatible),
+                true
+        );
+    }
+}