Skip to content

Commit

Permalink
refactor serialize BigInteger & BigDecimal support javascript
Browse files Browse the repository at this point in the history
  • Loading branch information
wenshao committed Aug 19, 2023
1 parent 3beb954 commit 7799c1d
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 17 deletions.
7 changes: 0 additions & 7 deletions core/src/main/java/com/alibaba/fastjson2/JSONFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
import com.alibaba.fastjson2.writer.ObjectWriterProvider;

import java.io.InputStream;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.time.ZoneId;
Expand Down Expand Up @@ -89,11 +87,6 @@ public NameCacheEntry2(String name, long value0, long value1) {
}
}

static final BigDecimal LOW = BigDecimal.valueOf(-9007199254740991L);
static final BigDecimal HIGH = BigDecimal.valueOf(9007199254740991L);
static final BigInteger LOW_BIGINT = BigInteger.valueOf(-9007199254740991L);
static final BigInteger HIGH_BIGINT = BigInteger.valueOf(9007199254740991L);

static final char[] CA = new char[]{
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
Expand Down
8 changes: 3 additions & 5 deletions core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import static com.alibaba.fastjson2.util.IOUtils.*;
import static com.alibaba.fastjson2.util.JDKUtils.*;
import static com.alibaba.fastjson2.util.TypeUtils.isInt64;
import static com.alibaba.fastjson2.util.TypeUtils.isJavaScriptSupport;

class JSONWriterUTF16
extends JSONWriter {
Expand Down Expand Up @@ -1242,8 +1243,7 @@ public final void writeBigInt(BigInteger value, long features) {
String str = value.toString(10);

features |= context.features;
boolean browserCompatible = (features & Feature.BrowserCompatible.mask) != 0
&& (value.compareTo(LOW_BIGINT) < 0 || value.compareTo(HIGH_BIGINT) > 0);
boolean browserCompatible = (features & Feature.BrowserCompatible.mask) != 0 && !isJavaScriptSupport(value);
boolean nonStringAsString = (features & (WriteNonStringValueAsString.mask | WriteLongAsString.mask)) != 0;
boolean writeAsString = browserCompatible || nonStringAsString;

Expand Down Expand Up @@ -1280,9 +1280,7 @@ public final void writeDecimal(BigDecimal value, long features, DecimalFormat fo
int precision = value.precision();
boolean nonStringAsString = (features & WriteNonStringValueAsString.mask) != 0;
boolean writeAsString = nonStringAsString
|| ((features & BrowserCompatible.mask) != 0
&& precision >= 16
&& (value.compareTo(LOW) < 0 || value.compareTo(HIGH) > 0));
|| ((features & BrowserCompatible.mask) != 0 && precision >= 16 && !TypeUtils.isJavaScriptSupport(value));

int off = this.off;
int minCapacity = off + precision + 7;
Expand Down
8 changes: 3 additions & 5 deletions core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import static com.alibaba.fastjson2.util.IOUtils.*;
import static com.alibaba.fastjson2.util.JDKUtils.*;
import static com.alibaba.fastjson2.util.TypeUtils.isInt64;
import static com.alibaba.fastjson2.util.TypeUtils.isJavaScriptSupport;

class JSONWriterUTF8
extends JSONWriter {
Expand Down Expand Up @@ -2493,8 +2494,7 @@ public final void writeBigInt(BigInteger value, long features) {

String str = value.toString(10);

if (((context.features | features) & Feature.BrowserCompatible.mask) != 0
&& (value.compareTo(LOW_BIGINT) < 0 || value.compareTo(HIGH_BIGINT) > 0)) {
if (((context.features | features) & Feature.BrowserCompatible.mask) != 0 && !isJavaScriptSupport(value)) {
writeString(str);
return;
}
Expand Down Expand Up @@ -2602,9 +2602,7 @@ public final void writeDecimal(BigDecimal value, long features, DecimalFormat fo
int precision = value.precision();
boolean nonStringAsString = (features & WriteNonStringValueAsString.mask) != 0;
boolean writeAsString = nonStringAsString
|| ((features & BrowserCompatible.mask) != 0
&& precision >= 16
&& (value.compareTo(LOW) < 0 || value.compareTo(HIGH) > 0));
|| ((features & BrowserCompatible.mask) != 0 && precision >= 16 && !TypeUtils.isJavaScriptSupport(value));

int off = this.off;
int minCapacity = off + precision + 7;
Expand Down
16 changes: 16 additions & 0 deletions core/src/main/java/com/alibaba/fastjson2/util/TypeUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ public class TypeUtils {
public static final BigInteger BIGINT_INT64_MIN = BigInteger.valueOf(Long.MIN_VALUE);
public static final BigInteger BIGINT_INT64_MAX = BigInteger.valueOf(Long.MAX_VALUE);

static final BigDecimal DECIMAL_JAVASCRIPT_LOW = BigDecimal.valueOf(-9007199254740991L);
static final BigDecimal DECIMAL_JAVASCRIPT_HIGH = BigDecimal.valueOf(9007199254740991L);

static final BigInteger BIGINT_JAVASCRIPT_LOW = BigInteger.valueOf(-9007199254740991L);
static final BigInteger BIGINT_JAVASCRIPT_HIGH = BigInteger.valueOf(9007199254740991L);

/**
* All the positive powers of 10 that can be
* represented exactly in double/float.
Expand Down Expand Up @@ -4271,4 +4277,14 @@ public static float floatValue(int signNum, long intCompact, int scale) {
int j = i >> eq | (Integer.signum(i & mask)) | sb;
return signNum * Math.scalb((float) j, Q_MIN_F - 2);
}

public static boolean isJavaScriptSupport(BigDecimal i) {
return i.compareTo(DECIMAL_JAVASCRIPT_LOW) >= 0
&& i.compareTo(DECIMAL_JAVASCRIPT_HIGH) <= 0;
}

public static boolean isJavaScriptSupport(BigInteger i) {
return i.compareTo(BIGINT_JAVASCRIPT_LOW) >= 0
&& i.compareTo(BIGINT_JAVASCRIPT_HIGH) <= 0;
}
}
32 changes: 32 additions & 0 deletions core/src/test/java/com/alibaba/fastjson2/util/TypeUtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import java.time.Instant;
import java.util.*;

import static com.alibaba.fastjson2.util.TypeUtils.BIGINT_JAVASCRIPT_HIGH;
import static com.alibaba.fastjson2.util.TypeUtils.BIGINT_JAVASCRIPT_LOW;
import static org.junit.jupiter.api.Assertions.*;

public class TypeUtilsTest {
Expand Down Expand Up @@ -804,4 +806,34 @@ public void isInt32_false() {
assertFalse(TypeUtils.isInt32(integer));
}
}

@Test
public void isJavaScriptSupport() {
BigInteger[] integers = new BigInteger[] {
BIGINT_JAVASCRIPT_LOW,
BIGINT_JAVASCRIPT_LOW.add(BigInteger.ONE),
BIGINT_JAVASCRIPT_HIGH,
BIGINT_JAVASCRIPT_HIGH.subtract(BigInteger.ONE)
};

for (BigInteger integer : integers) {
assertTrue(TypeUtils.isJavaScriptSupport(integer));
}

for (BigInteger integer : integers) {
assertTrue(TypeUtils.isJavaScriptSupport(new BigDecimal(integer)));
}
}

@Test
public void isJavaScriptSupport_false() {
BigInteger[] integers = new BigInteger[] {
BIGINT_JAVASCRIPT_LOW.subtract(BigInteger.ONE),
BIGINT_JAVASCRIPT_HIGH.add(BigInteger.ONE)
};

for (BigInteger integer : integers) {
assertFalse(TypeUtils.isJavaScriptSupport(integer));
}
}
}

0 comments on commit 7799c1d

Please sign in to comment.