Skip to content

Commit d120ce9

Browse files
committed
fix WriteNullListAsEmpty, for issue #878
1 parent 9fb7af3 commit d120ce9

13 files changed

+189
-68
lines changed

core/src/main/java/com/alibaba/fastjson2/JSONWriterJSONB.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,25 @@ public void writeNull() {
248248
bytes[off++] = BC_NULL;
249249
}
250250

251+
@Override
252+
public void writeStringNull() {
253+
if (off == bytes.length) {
254+
int minCapacity = off + 1;
255+
int oldCapacity = bytes.length;
256+
int newCapacity = oldCapacity + (oldCapacity >> 1);
257+
if (newCapacity - minCapacity < 0) {
258+
newCapacity = minCapacity;
259+
}
260+
if (newCapacity - maxArraySize > 0) {
261+
throw new OutOfMemoryError();
262+
}
263+
264+
// minCapacity is usually close to size, so this is a win:
265+
bytes = Arrays.copyOf(bytes, newCapacity);
266+
}
267+
bytes[off++] = BC_NULL;
268+
}
269+
251270
@Override
252271
public void endArray() {
253272
level--;

core/src/main/java/com/alibaba/fastjson2/writer/FieldWriterListField.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import java.lang.reflect.Type;
88
import java.util.List;
99

10+
import static com.alibaba.fastjson2.JSONWriter.Feature.*;
11+
1012
final class FieldWriterListField<T>
1113
extends FieldWriterList<T> {
1214
protected FieldWriterListField(
@@ -48,7 +50,7 @@ public boolean write(JSONWriter jsonWriter, T object) {
4850

4951
if (value == null) {
5052
long features = this.features | context.getFeatures();
51-
if ((features & (JSONWriter.Feature.WriteNulls.mask | JSONWriter.Feature.NullAsDefaultValue.mask | JSONWriter.Feature.WriteNullListAsEmpty.mask)) != 0) {
53+
if ((features & (WriteNulls.mask | NullAsDefaultValue.mask | WriteNullListAsEmpty.mask)) != 0) {
5254
writeFieldName(jsonWriter);
5355
jsonWriter.writeArrayNull();
5456
return true;

core/src/main/java/com/alibaba/fastjson2/writer/FieldWriterListFunc.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import java.util.List;
88
import java.util.function.Function;
99

10+
import static com.alibaba.fastjson2.JSONWriter.Feature.*;
11+
1012
final class FieldWriterListFunc<T>
1113
extends FieldWriterList<T> {
1214
final Function<T, List> function;
@@ -46,15 +48,15 @@ public boolean write(JSONWriter jsonWriter, T object) {
4648

4749
if (list == null) {
4850
long features = this.features | jsonWriter.getFeatures();
49-
if ((features & (JSONWriter.Feature.WriteNulls.mask | JSONWriter.Feature.NullAsDefaultValue.mask | JSONWriter.Feature.WriteNullListAsEmpty.mask)) == 0) {
51+
if ((features & (WriteNulls.mask | NullAsDefaultValue.mask | WriteNullListAsEmpty.mask)) == 0) {
5052
return false;
5153
}
5254
writeFieldName(jsonWriter);
5355
jsonWriter.writeArrayNull();
5456
return true;
5557
}
5658

57-
if ((features & JSONWriter.Feature.NotWriteEmptyArray.mask) != 0 && list.isEmpty()) {
59+
if ((features & NotWriteEmptyArray.mask) != 0 && list.isEmpty()) {
5860
return false;
5961
}
6062

core/src/main/java/com/alibaba/fastjson2/writer/FieldWriterListMethod.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import java.lang.reflect.Type;
99
import java.util.List;
1010

11+
import static com.alibaba.fastjson2.JSONWriter.Feature.*;
12+
1113
final class FieldWriterListMethod<T>
1214
extends FieldWriterList<T> {
1315
protected FieldWriterListMethod(
@@ -47,7 +49,7 @@ public boolean write(JSONWriter jsonWriter, T object) {
4749

4850
long features = this.features | jsonWriter.getFeatures();
4951
if (value == null) {
50-
if ((features & (JSONWriter.Feature.WriteNulls.mask | JSONWriter.Feature.NullAsDefaultValue.mask | JSONWriter.Feature.WriteNullListAsEmpty.mask)) != 0) {
52+
if ((features & (WriteNulls.mask | NullAsDefaultValue.mask | WriteNullListAsEmpty.mask)) != 0) {
5153
writeFieldName(jsonWriter);
5254
jsonWriter.writeArrayNull();
5355
return true;
@@ -56,7 +58,7 @@ public boolean write(JSONWriter jsonWriter, T object) {
5658
}
5759
}
5860

59-
if ((features & JSONWriter.Feature.NotWriteEmptyArray.mask) != 0 && value.isEmpty()) {
61+
if ((features & NotWriteEmptyArray.mask) != 0 && value.isEmpty()) {
6062
return false;
6163
}
6264

core/src/main/java/com/alibaba/fastjson2/writer/FieldWriterListStrFunc.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import java.util.List;
88
import java.util.function.Function;
99

10+
import static com.alibaba.fastjson2.JSONWriter.Feature.*;
11+
1012
final class FieldWriterListStrFunc<T>
1113
extends FieldWriter<T> {
1214
final Function<T, List> function;
@@ -45,7 +47,7 @@ public boolean write(JSONWriter jsonWriter, T object) {
4547

4648
long features = this.features | jsonWriter.getFeatures();
4749
if (list == null) {
48-
if ((features & (JSONWriter.Feature.WriteNulls.mask | JSONWriter.Feature.NullAsDefaultValue.mask | JSONWriter.Feature.WriteNullListAsEmpty.mask)) != 0) {
50+
if ((features & (WriteNulls.mask | NullAsDefaultValue.mask | WriteNullListAsEmpty.mask)) != 0) {
4951
writeFieldName(jsonWriter);
5052
jsonWriter.writeArrayNull();
5153
return true;
@@ -54,7 +56,7 @@ public boolean write(JSONWriter jsonWriter, T object) {
5456
}
5557
}
5658

57-
if ((features & JSONWriter.Feature.NotWriteEmptyArray.mask) != 0 && list.isEmpty()) {
59+
if ((features & NotWriteEmptyArray.mask) != 0 && list.isEmpty()) {
5860
return false;
5961
}
6062

core/src/main/java/com/alibaba/fastjson2/writer/FieldWriterObjectArrayField.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import java.lang.reflect.Field;
88
import java.lang.reflect.Type;
99

10+
import static com.alibaba.fastjson2.JSONWriter.Feature.*;
11+
1012
final class FieldWriterObjectArrayField<T>
1113
extends FieldWriter<T> {
1214
final Type itemType;
@@ -61,7 +63,7 @@ public boolean write(JSONWriter jsonWriter, T object) {
6163

6264
if (value == null) {
6365
long features = this.features | jsonWriter.getFeatures();
64-
if ((features & (JSONWriter.Feature.WriteNulls.mask | JSONWriter.Feature.NullAsDefaultValue.mask | JSONWriter.Feature.WriteNullListAsEmpty.mask)) != 0) {
66+
if ((features & (WriteNulls.mask | NullAsDefaultValue.mask | WriteNullListAsEmpty.mask)) != 0) {
6567
writeFieldName(jsonWriter);
6668
jsonWriter.writeArrayNull();
6769
return true;

core/src/main/java/com/alibaba/fastjson2/writer/FieldWriterObjectArrayMethod.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import java.lang.reflect.Method;
99
import java.lang.reflect.Type;
1010

11+
import static com.alibaba.fastjson2.JSONWriter.Feature.*;
12+
1113
final class FieldWriterObjectArrayMethod<T>
1214
extends FieldWriter<T> {
1315
final Type itemType;
@@ -62,7 +64,7 @@ public boolean write(JSONWriter jsonWriter, T object) {
6264

6365
if (value == null) {
6466
long features = this.features | jsonWriter.getFeatures();
65-
if ((features & (JSONWriter.Feature.WriteNulls.mask | JSONWriter.Feature.NullAsDefaultValue.mask | JSONWriter.Feature.WriteNullListAsEmpty.mask)) != 0) {
67+
if ((features & (WriteNulls.mask | NullAsDefaultValue.mask | WriteNullListAsEmpty.mask)) != 0) {
6668
writeFieldName(jsonWriter);
6769
jsonWriter.writeArrayNull();
6870
return true;

core/src/main/java/com/alibaba/fastjson2/writer/ObjectWriterBaseModule.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -874,7 +874,8 @@ public ObjectWriter getObjectWriter(Type objectType, Class objectClass) {
874874

875875
if (Map.Entry.class.isAssignableFrom(objectClass)) {
876876
String objectClassName = objectClass.getName();
877-
if (!"org.apache.commons.lang3.tuple.ImmutablePair".equals(objectClassName) && !"org.apache.commons.lang3.tuple.MutablePair".equals(objectClassName)
877+
if (!"org.apache.commons.lang3.tuple.ImmutablePair".equals(objectClassName)
878+
&& !"org.apache.commons.lang3.tuple.MutablePair".equals(objectClassName)
878879
) {
879880
return ObjectWriterImplMapEntry.INSTANCE;
880881
}

core/src/main/java/com/alibaba/fastjson2/writer/ObjectWriterCreatorASM.java

Lines changed: 63 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import java.util.concurrent.atomic.AtomicLong;
1919
import java.util.concurrent.atomic.AtomicLongArray;
2020

21+
import static com.alibaba.fastjson2.JSONWriter.Feature.*;
2122
import static com.alibaba.fastjson2.util.JDKUtils.UNSAFE_SUPPORT;
2223

2324
public class ObjectWriterCreatorASM
@@ -1802,17 +1803,17 @@ private void gwFieldValueObject(
18021803
|| fieldClass == AtomicIntegerArray.class
18031804
|| Collection.class.isAssignableFrom(fieldClass)
18041805
|| fieldClass.isArray()) {
1805-
nullFeatures |= JSONWriter.Feature.WriteNullListAsEmpty.mask;
1806-
nullFeatures |= JSONWriter.Feature.NullAsDefaultValue.mask;
1806+
nullFeatures |= WriteNullListAsEmpty.mask;
1807+
nullFeatures |= NullAsDefaultValue.mask;
18071808
} else if (Number.class.isAssignableFrom(fieldClass)) {
1808-
nullFeatures |= JSONWriter.Feature.WriteNullNumberAsZero.mask;
1809-
nullFeatures |= JSONWriter.Feature.NullAsDefaultValue.mask;
1809+
nullFeatures |= WriteNullNumberAsZero.mask;
1810+
nullFeatures |= NullAsDefaultValue.mask;
18101811
} else if (fieldClass == Boolean.class) {
1811-
nullFeatures |= JSONWriter.Feature.WriteNullBooleanAsFalse.mask;
1812-
nullFeatures |= JSONWriter.Feature.NullAsDefaultValue.mask;
1812+
nullFeatures |= WriteNullBooleanAsFalse.mask;
1813+
nullFeatures |= NullAsDefaultValue.mask;
18131814
} else if (fieldClass == String.class) {
1814-
nullFeatures |= JSONWriter.Feature.WriteNullStringAsEmpty.mask;
1815-
nullFeatures |= JSONWriter.Feature.NullAsDefaultValue.mask;
1815+
nullFeatures |= WriteNullStringAsEmpty.mask;
1816+
nullFeatures |= NullAsDefaultValue.mask;
18161817
}
18171818
mwc.genIsEnabled(nullFeatures, notNull_);
18181819
// mw.visitVarInsn(Opcodes.ILOAD, mwc.var(WRITE_NULLS));
@@ -1946,9 +1947,7 @@ private void gwFieldValueList(
19461947
mw.visitJumpInsn(Opcodes.GOTO, notNull_);
19471948

19481949
mw.visitLabel(null_);
1949-
// if (!jw.isWriteNulls())
1950-
mw.visitVarInsn(Opcodes.ILOAD, mwc.var(WRITE_NULLS));
1951-
mw.visitJumpInsn(Opcodes.IFEQ, notNull_);
1950+
mwc.genIsEnabled(WriteNulls.mask | NullAsDefaultValue.mask | WriteNullListAsEmpty.mask, notNull_);
19521951

19531952
// writeFieldName(w);
19541953
gwFieldName(mwc, i);
@@ -2044,10 +2043,11 @@ private void gwInt32(
20442043

20452044
mw.visitJumpInsn(Opcodes.IFNONNULL, notNull_);
20462045

2047-
mw.visitVarInsn(Opcodes.ILOAD, mwc.var(WRITE_NULLS));
2048-
mw.visitJumpInsn(Opcodes.IFNE, writeNullValue_);
2049-
2050-
mw.visitJumpInsn(Opcodes.GOTO, endIfNull_);
2046+
mwc.genIsEnabled(
2047+
WriteNulls.mask | NullAsDefaultValue.mask | WriteNullNumberAsZero.mask,
2048+
writeNullValue_,
2049+
endIfNull_
2050+
);
20512051

20522052
mw.visitLabel(writeNullValue_);
20532053

@@ -2104,10 +2104,11 @@ private void gwInt64(
21042104

21052105
mw.visitJumpInsn(Opcodes.IFNONNULL, notNull_);
21062106

2107-
mw.visitVarInsn(Opcodes.ILOAD, mwc.var(WRITE_NULLS));
2108-
mw.visitJumpInsn(Opcodes.IFNE, writeNullValue_);
2109-
2110-
mw.visitJumpInsn(Opcodes.GOTO, endIfNull_);
2107+
mwc.genIsEnabled(
2108+
WriteNulls.mask | NullAsDefaultValue.mask | WriteNullNumberAsZero.mask,
2109+
writeNullValue_,
2110+
endIfNull_
2111+
);
21112112

21122113
mw.visitLabel(writeNullValue_);
21132114

@@ -2663,35 +2664,38 @@ private void gwFieldValueString(
26632664

26642665
Label writeNullValue_ = new Label(), writeNull_ = new Label();
26652666

2666-
final long defaultValueMask = JSONWriter.Feature.NullAsDefaultValue.mask
2667-
| JSONWriter.Feature.WriteNullNumberAsZero.mask
2668-
| JSONWriter.Feature.WriteNullBooleanAsFalse.mask
2669-
| JSONWriter.Feature.WriteNullListAsEmpty.mask
2670-
| JSONWriter.Feature.WriteNullStringAsEmpty.mask;
2667+
final long defaultValueMask = NullAsDefaultValue.mask
2668+
| WriteNullNumberAsZero.mask
2669+
| WriteNullBooleanAsFalse.mask
2670+
| WriteNullListAsEmpty.mask
2671+
| WriteNullStringAsEmpty.mask;
26712672

26722673
// if (!jw.isWriteNulls())
26732674
if ((features & (JSONWriter.Feature.WriteNulls.mask
26742675
| defaultValueMask)) == 0) {
2675-
mw.visitVarInsn(Opcodes.ILOAD, mwc.var(WRITE_NULLS));
2676-
mw.visitJumpInsn(Opcodes.IFNE, writeNull_);
2677-
2678-
mw.visitJumpInsn(Opcodes.GOTO, endIfNull_);
2676+
mwc.genIsEnabled(
2677+
WriteNulls.mask | NullAsDefaultValue.mask | WriteNullStringAsEmpty.mask,
2678+
writeNull_,
2679+
endIfNull_
2680+
);
26792681
}
26802682

26812683
mw.visitLabel(writeNull_);
2684+
mwc.genIsDisabled(NotWriteDefaultValue.mask, endIfNull_);
2685+
26822686
// writeFieldName(w);
26832687
gwFieldName(mwc, i);
26842688

26852689
if ((features & defaultValueMask) == 0) {
2686-
long mask = JSONWriter.Feature.NullAsDefaultValue.mask;
2690+
long mask = NullAsDefaultValue.mask;
26872691
if (fieldClass == String.class) {
2688-
mask |= JSONWriter.Feature.WriteNullStringAsEmpty.mask;
2692+
mask |= WriteNullStringAsEmpty.mask;
26892693
} else if (fieldClass == Boolean.class) {
2690-
mask |= JSONWriter.Feature.WriteNullBooleanAsFalse.mask;
2694+
mask |= WriteNullBooleanAsFalse.mask;
26912695
} else if (Number.class.isAssignableFrom(fieldClass)) {
26922696
mask |= JSONWriter.Feature.WriteNullNumberAsZero.mask;
26932697
} else if (Collection.class.isAssignableFrom(fieldClass)) {
2694-
mask |= JSONWriter.Feature.WriteNullListAsEmpty.mask;
2698+
mask |= WriteNullListAsEmpty.mask;
26952699
}
26962700

26972701
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
@@ -3094,9 +3098,8 @@ void genVariantsMethodBefore() {
30943098
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "getFeatures", "()J", false);
30953099
mw.visitVarInsn(Opcodes.LSTORE, var2(CONTEXT_FEATURES));
30963100

3097-
genIsEnabled(JSONWriter.Feature.NotWriteDefaultValue.mask);
3098-
mw.visitInsn(Opcodes.DUP);
3099-
mw.visitVarInsn(Opcodes.ISTORE, var(NOT_WRITE_DEFAULT_VALUE));
3101+
genIsEnabledAndAssign(NotWriteDefaultValue.mask, var(NOT_WRITE_DEFAULT_VALUE));
3102+
mw.visitVarInsn(Opcodes.ILOAD, var(NOT_WRITE_DEFAULT_VALUE));
31003103
mw.visitJumpInsn(Opcodes.IFEQ, notDefault_);
31013104

31023105
mw.visitInsn(Opcodes.ICONST_0);
@@ -3105,14 +3108,10 @@ void genVariantsMethodBefore() {
31053108

31063109
mw.visitLabel(notDefault_);
31073110

3108-
long features = JSONWriter.Feature.WriteNulls.mask
3109-
| JSONWriter.Feature.NullAsDefaultValue.mask
3110-
| JSONWriter.Feature.WriteNullBooleanAsFalse.mask
3111-
| JSONWriter.Feature.WriteNullStringAsEmpty.mask
3112-
| JSONWriter.Feature.WriteNullNumberAsZero.mask
3113-
| JSONWriter.Feature.WriteNullListAsEmpty.mask;
3114-
genIsEnabled(features);
3115-
mw.visitVarInsn(Opcodes.ISTORE, var(WRITE_NULLS));
3111+
long features = WriteNulls.mask | NullAsDefaultValue.mask;
3112+
// genIsEnabled(features);
3113+
// mw.visitVarInsn(Opcodes.ISTORE, var(WRITE_NULLS));
3114+
genIsEnabledAndAssign(features, var(WRITE_NULLS));
31163115

31173116
mw.visitLabel(end_);
31183117
}
@@ -3126,19 +3125,32 @@ void genIsEnabled(long features, Label elseLabel) {
31263125
mw.visitJumpInsn(Opcodes.IFEQ, elseLabel);
31273126
}
31283127

3129-
void genIsEnabled(long features) {
3130-
Label L1 = new Label(), L2 = new Label();
3128+
void genIsDisabled(long features, Label elseLabel) {
31313129
mw.visitVarInsn(Opcodes.LLOAD, var2(CONTEXT_FEATURES));
31323130
mw.visitLdcInsn(features);
31333131
mw.visitInsn(Opcodes.LAND);
31343132
mw.visitInsn(Opcodes.LCONST_0);
31353133
mw.visitInsn(Opcodes.LCMP);
3136-
mw.visitJumpInsn(Opcodes.IFEQ, L1);
3137-
mw.visitInsn(Opcodes.ICONST_1);
3138-
mw.visitJumpInsn(Opcodes.GOTO, L2);
3139-
mw.visitLabel(L1);
3140-
mw.visitInsn(Opcodes.ICONST_0);
3141-
mw.visitLabel(L2);
3134+
mw.visitJumpInsn(Opcodes.IFNE, elseLabel);
3135+
}
3136+
3137+
void genIsEnabled(long features, Label trueLabel, Label falseLabel) {
3138+
mw.visitVarInsn(Opcodes.LLOAD, var2(CONTEXT_FEATURES));
3139+
mw.visitLdcInsn(features);
3140+
mw.visitInsn(Opcodes.LAND);
3141+
mw.visitInsn(Opcodes.LCONST_0);
3142+
mw.visitInsn(Opcodes.LCMP);
3143+
mw.visitJumpInsn(Opcodes.IFEQ, falseLabel);
3144+
mw.visitJumpInsn(Opcodes.GOTO, trueLabel);
3145+
}
3146+
3147+
void genIsEnabledAndAssign(long features, int var) {
3148+
mw.visitVarInsn(Opcodes.LLOAD, var2(CONTEXT_FEATURES));
3149+
mw.visitLdcInsn(features);
3150+
mw.visitInsn(Opcodes.LAND);
3151+
mw.visitInsn(Opcodes.LCONST_0);
3152+
mw.visitInsn(Opcodes.LCMP);
3153+
mw.visitVarInsn(Opcodes.ISTORE, var);
31423154
}
31433155

31443156
private void loadFieldType(int fieldIndex, Type fieldType) {

core/src/main/java/com/alibaba/fastjson2/writer/ObjectWriterImplInt32Array.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66

77
import java.lang.reflect.Type;
88

9+
import static com.alibaba.fastjson2.JSONWriter.Feature.NullAsDefaultValue;
10+
import static com.alibaba.fastjson2.JSONWriter.Feature.WriteNullListAsEmpty;
11+
912
final class ObjectWriterImplInt32Array
1013
extends ObjectWriterBaseModule.PrimitiveImpl {
1114
static final ObjectWriterImplInt32Array INSTANCE = new ObjectWriterImplInt32Array();
@@ -15,7 +18,7 @@ final class ObjectWriterImplInt32Array
1518
@Override
1619
public void write(JSONWriter jsonWriter, Object object, Object fieldName, Type fieldType, long features) {
1720
if (object == null) {
18-
if (jsonWriter.isEnabled(JSONWriter.Feature.NullAsDefaultValue.mask | JSONWriter.Feature.WriteNullListAsEmpty.mask)) {
21+
if (jsonWriter.isEnabled(NullAsDefaultValue.mask | WriteNullListAsEmpty.mask)) {
1922
jsonWriter.startArray();
2023
jsonWriter.endArray();
2124
} else {

0 commit comments

Comments
 (0)