mirror of https://github.com/alibaba/fastjson2.git
fix improve feature of NullAsDefaultValue, for issue #3518
This commit is contained in:
parent
2f1f77bd6d
commit
ae093fa8fc
|
@ -1147,6 +1147,18 @@ public abstract class JSONWriter
|
|||
|
||||
public abstract void writeNull();
|
||||
|
||||
public void writeObjectNull(Class<?> fieldClass) {
|
||||
if ((this.context.features & (MASK_NULL_AS_DEFAULT_VALUE)) != 0) {
|
||||
if (fieldClass == Character.class) {
|
||||
writeString("\u0000");
|
||||
} else {
|
||||
writeRaw('{', '}');
|
||||
}
|
||||
} else {
|
||||
writeNull();
|
||||
}
|
||||
}
|
||||
|
||||
public void writeStringNull() {
|
||||
String raw;
|
||||
long features = this.context.features;
|
||||
|
@ -1176,6 +1188,16 @@ public abstract class JSONWriter
|
|||
}
|
||||
}
|
||||
|
||||
public final void writeDecimalNull() {
|
||||
if ((this.context.features & MASK_NULL_AS_DEFAULT_VALUE) != 0) {
|
||||
writeDouble(0.0);
|
||||
} else if ((this.context.features & MASK_WRITE_NULL_NUMBER_AS_ZERO) != 0) {
|
||||
writeInt32(0);
|
||||
} else {
|
||||
writeNull();
|
||||
}
|
||||
}
|
||||
|
||||
public final void writeInt64Null() {
|
||||
if ((this.context.features & (MASK_NULL_AS_DEFAULT_VALUE | MASK_WRITE_NULL_NUMBER_AS_ZERO)) != 0) {
|
||||
writeInt64(0);
|
||||
|
|
|
@ -1045,7 +1045,7 @@ class JSONWriterUTF16
|
|||
|
||||
public final void writeDecimal(BigDecimal value, long features, DecimalFormat format) {
|
||||
if (value == null) {
|
||||
writeNumberNull();
|
||||
writeDecimalNull();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -2371,7 +2371,7 @@ final class JSONWriterUTF8
|
|||
@Override
|
||||
public final void writeDecimal(BigDecimal value, long features, DecimalFormat format) {
|
||||
if (value == null) {
|
||||
writeNumberNull();
|
||||
writeDecimalNull();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ final class FieldWriterBigDecimalField<T>
|
|||
BigDecimal value = (BigDecimal) getFieldValue(object);
|
||||
if (value == null) {
|
||||
long features = this.features | jsonWriter.getFeatures();
|
||||
if ((features & JSONWriter.Feature.WriteNulls.mask) == 0) {
|
||||
if ((features & (JSONWriter.Feature.WriteNulls.mask | JSONWriter.Feature.NullAsDefaultValue.mask)) == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ final class FieldWriterBigDecimalFunc<T>
|
|||
|
||||
if (value == null) {
|
||||
long features = this.features | jsonWriter.getFeatures();
|
||||
if ((features & JSONWriter.Feature.WriteNulls.mask) == 0) {
|
||||
if ((features & (JSONWriter.Feature.WriteNulls.mask | JSONWriter.Feature.NullAsDefaultValue.mask)) == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ final class FieldWriterBigDecimalMethod<T>
|
|||
|
||||
if (value == null) {
|
||||
long features = this.features | jsonWriter.getFeatures();
|
||||
if ((features & JSONWriter.Feature.WriteNulls.mask) == 0) {
|
||||
if ((features & (JSONWriter.Feature.WriteNulls.mask | JSONWriter.Feature.NullAsDefaultValue.mask)) == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ final class FieldWriterBigIntField<T>
|
|||
BigInteger value = (BigInteger) getFieldValue(object);
|
||||
if (value == null) {
|
||||
long features = this.features | jsonWriter.getFeatures();
|
||||
if ((features & JSONWriter.Feature.WriteNulls.mask) == 0) {
|
||||
if ((features & (JSONWriter.Feature.WriteNulls.mask | JSONWriter.Feature.NullAsDefaultValue.mask)) == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ final class FieldWriterBigIntFunc<T>
|
|||
BigInteger value = function.apply(o);
|
||||
if (value == null) {
|
||||
long features = this.features | jsonWriter.getFeatures();
|
||||
if ((features & JSONWriter.Feature.WriteNulls.mask) == 0) {
|
||||
if ((features & (JSONWriter.Feature.WriteNulls.mask | JSONWriter.Feature.NullAsDefaultValue.mask)) == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,11 +58,12 @@ final class FieldWriterDoubleFunc<T>
|
|||
|
||||
if (value == null) {
|
||||
long features = jsonWriter.getFeatures(this.features);
|
||||
if ((features & JSONWriter.Feature.WriteNulls.mask) != 0
|
||||
&& (features & JSONWriter.Feature.NotWriteDefaultValue.mask) == 0
|
||||
) {
|
||||
if ((features & (JSONWriter.Feature.WriteNulls.mask | JSONWriter.Feature.NullAsDefaultValue.mask)) == 0) {
|
||||
return false;
|
||||
}
|
||||
if ((features & JSONWriter.Feature.NotWriteDefaultValue.mask) == 0) {
|
||||
writeFieldName(jsonWriter);
|
||||
jsonWriter.writeNumberNull();
|
||||
jsonWriter.writeDecimalNull();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -58,11 +58,12 @@ final class FieldWriterFloatFunc<T>
|
|||
|
||||
if (value == null) {
|
||||
long features = jsonWriter.getFeatures(this.features);
|
||||
if ((features & JSONWriter.Feature.WriteNulls.mask) != 0
|
||||
&& (features & JSONWriter.Feature.NotWriteDefaultValue.mask) == 0
|
||||
) {
|
||||
if ((features & (JSONWriter.Feature.WriteNulls.mask | JSONWriter.Feature.NullAsDefaultValue.mask)) == 0) {
|
||||
return false;
|
||||
}
|
||||
if ((features & JSONWriter.Feature.NotWriteDefaultValue.mask) == 0) {
|
||||
writeFieldName(jsonWriter);
|
||||
jsonWriter.writeNumberNull();
|
||||
jsonWriter.writeDecimalNull();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -46,7 +46,7 @@ abstract class FieldWriterInt16<T>
|
|||
|
||||
if (value == null) {
|
||||
long features = this.features | jsonWriter.getFeatures();
|
||||
if ((features & JSONWriter.Feature.WriteNulls.mask) == 0) {
|
||||
if ((features & (JSONWriter.Feature.WriteNulls.mask | JSONWriter.Feature.NullAsDefaultValue.mask)) == 0) {
|
||||
return false;
|
||||
}
|
||||
writeFieldName(jsonWriter);
|
||||
|
|
|
@ -45,7 +45,7 @@ abstract class FieldWriterInt8<T>
|
|||
|
||||
if (value == null) {
|
||||
long features = this.features | jsonWriter.getFeatures();
|
||||
if ((features & JSONWriter.Feature.WriteNulls.mask) == 0) {
|
||||
if ((features & (JSONWriter.Feature.WriteNulls.mask | JSONWriter.Feature.NullAsDefaultValue.mask)) == 0) {
|
||||
return false;
|
||||
}
|
||||
writeFieldName(jsonWriter);
|
||||
|
|
|
@ -272,7 +272,10 @@ public class FieldWriterObject<T>
|
|||
|
||||
// (features & JSONWriter.Feature.WriteNullNumberAsZero.mask) != 0
|
||||
if (value == null) {
|
||||
if ((features & WriteNulls.mask) != 0 && (features & NotWriteDefaultValue.mask) == 0) {
|
||||
if ((features & (JSONWriter.Feature.WriteNulls.mask | JSONWriter.Feature.NullAsDefaultValue.mask)) == 0) {
|
||||
return false;
|
||||
}
|
||||
if ((features & NotWriteDefaultValue.mask) == 0) {
|
||||
writeFieldName(jsonWriter);
|
||||
if (array) {
|
||||
jsonWriter.writeArrayNull();
|
||||
|
@ -283,7 +286,7 @@ public class FieldWriterObject<T>
|
|||
|| fieldClass == StringBuilder.class) {
|
||||
jsonWriter.writeStringNull();
|
||||
} else {
|
||||
jsonWriter.writeNull();
|
||||
jsonWriter.writeObjectNull(fieldClass);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
|
|
|
@ -59,20 +59,18 @@ abstract class FieldWriterObjectFinal<T>
|
|||
|
||||
if (value == null) {
|
||||
long features = this.features | jsonWriter.getFeatures();
|
||||
if ((features & JSONWriter.Feature.WriteNulls.mask) != 0) {
|
||||
if ((features & (JSONWriter.Feature.WriteNulls.mask | JSONWriter.Feature.NullAsDefaultValue.mask)) == 0) {
|
||||
return false;
|
||||
}
|
||||
writeFieldName(jsonWriter);
|
||||
|
||||
if (fieldClass.isArray()) {
|
||||
jsonWriter.writeArrayNull();
|
||||
} else if (fieldClass == StringBuffer.class || fieldClass == StringBuilder.class) {
|
||||
jsonWriter.writeStringNull();
|
||||
} else {
|
||||
jsonWriter.writeNull();
|
||||
jsonWriter.writeObjectNull(fieldClass);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ObjectWriter valueWriter = getObjectWriter(jsonWriter, fieldClass);
|
||||
|
|
|
@ -2526,7 +2526,7 @@ public class ObjectWriterCreatorASM
|
|||
// writeFieldName(w);
|
||||
gwFieldName(mwc, fieldWriter, i);
|
||||
|
||||
// jw.writeNulll
|
||||
// jw.writeNull
|
||||
mw.aload(JSON_WRITER);
|
||||
mw.invokevirtual(TYPE_JSON_WRITER, "writeNull", "()V");
|
||||
|
||||
|
@ -2813,6 +2813,8 @@ public class ObjectWriterCreatorASM
|
|||
} else if (fieldClass == String.class) {
|
||||
nullFeatures |= WriteNullStringAsEmpty.mask;
|
||||
nullFeatures |= NullAsDefaultValue.mask;
|
||||
} else {
|
||||
nullFeatures |= NullAsDefaultValue.mask;
|
||||
}
|
||||
mwc.genIsEnabled(nullFeatures, notNull_);
|
||||
// mw.iload(mwc.var(WRITE_NULLS));
|
||||
|
@ -2822,13 +2824,19 @@ public class ObjectWriterCreatorASM
|
|||
// writeFieldName(w);
|
||||
gwFieldName(mwc, fieldWriter, i);
|
||||
|
||||
// jw.writeNulll
|
||||
// jw.writeNull
|
||||
mw.aload(JSON_WRITER);
|
||||
String WRITE_NULL_METHOD;
|
||||
String WRITE_NULL_DESC = "()V";
|
||||
if (fieldClass == AtomicLongArray.class
|
||||
|| fieldClass == AtomicIntegerArray.class
|
||||
|| Collection.class.isAssignableFrom(fieldClass)
|
||||
|| fieldClass.isArray()) {
|
||||
WRITE_NULL_METHOD = "writeArrayNull";
|
||||
} else if (fieldClass == Float.class
|
||||
|| fieldClass == Double.class
|
||||
|| fieldClass == BigDecimal.class) {
|
||||
WRITE_NULL_METHOD = "writeDecimalNull";
|
||||
} else if (Number.class.isAssignableFrom(fieldClass)) {
|
||||
WRITE_NULL_METHOD = "writeNumberNull";
|
||||
} else if (fieldClass == Boolean.class) {
|
||||
|
@ -2839,10 +2847,11 @@ public class ObjectWriterCreatorASM
|
|||
|| fieldClass == StringBuilder.class) {
|
||||
WRITE_NULL_METHOD = "writeStringNull";
|
||||
} else {
|
||||
WRITE_NULL_METHOD = "writeNull";
|
||||
WRITE_NULL_METHOD = "writeObjectNull";
|
||||
WRITE_NULL_DESC = "(Ljava/lang/Class;)V";
|
||||
mwc.loadFieldClass(i, fieldClass);
|
||||
}
|
||||
mw.aload(JSON_WRITER);
|
||||
mw.invokevirtual(TYPE_JSON_WRITER, WRITE_NULL_METHOD, "()V");
|
||||
mw.invokevirtual(TYPE_JSON_WRITER, WRITE_NULL_METHOD, WRITE_NULL_DESC);
|
||||
|
||||
mw.visitLabel(notNull_);
|
||||
}
|
||||
|
@ -3005,7 +3014,7 @@ public class ObjectWriterCreatorASM
|
|||
// writeFieldName(w);
|
||||
gwFieldName(mwc, fieldWriter, i);
|
||||
|
||||
// jw.writeNulll
|
||||
// jw.writeNull
|
||||
mw.aload(JSON_WRITER);
|
||||
mw.invokevirtual(TYPE_JSON_WRITER, "writeArrayNull", "()V");
|
||||
|
||||
|
@ -3239,7 +3248,7 @@ public class ObjectWriterCreatorASM
|
|||
gwFieldName(mwc, fieldWriter, i);
|
||||
|
||||
mw.aload(JSON_WRITER);
|
||||
mw.invokevirtual(TYPE_JSON_WRITER, "writeNumberNull", "()V");
|
||||
mw.invokevirtual(TYPE_JSON_WRITER, "writeDecimalNull", "()V");
|
||||
|
||||
mw.goto_(endIfNull_);
|
||||
|
||||
|
@ -3300,7 +3309,7 @@ public class ObjectWriterCreatorASM
|
|||
gwFieldName(mwc, fieldWriter, i);
|
||||
|
||||
mw.aload(JSON_WRITER);
|
||||
mw.invokevirtual(TYPE_JSON_WRITER, "writeNumberNull", "()V");
|
||||
mw.invokevirtual(TYPE_JSON_WRITER, "writeDecimalNull", "()V");
|
||||
|
||||
mw.goto_(endIfNull_);
|
||||
|
||||
|
@ -3484,7 +3493,7 @@ public class ObjectWriterCreatorASM
|
|||
mw.visitLabel(writeNull_);
|
||||
gwFieldName(mwc, fieldWriter, i);
|
||||
|
||||
// jw.writeNulll
|
||||
// jw.writeNull
|
||||
mw.aload(JSON_WRITER);
|
||||
mw.invokevirtual(TYPE_JSON_WRITER, "writeNull", "()V");
|
||||
|
||||
|
@ -4190,7 +4199,7 @@ public class ObjectWriterCreatorASM
|
|||
mw.invokevirtual(TYPE_JSON_WRITER, "writeString", "(Ljava/lang/String;)V");
|
||||
mw.goto_(endIfNull_);
|
||||
|
||||
// jw.writeNulll
|
||||
// jw.writeNull
|
||||
mw.visitLabel(writeNullValue_);
|
||||
mw.aload(JSON_WRITER);
|
||||
mw.invokevirtual(TYPE_JSON_WRITER, "writeStringNull", "()V");
|
||||
|
|
|
@ -11,7 +11,7 @@ public class Issue364 {
|
|||
@Test
|
||||
public void test() {
|
||||
TestBean bean = new TestBean();
|
||||
assertEquals("{\"msg\":\"\"}", JSON.toJSONString(bean, JSONWriter.Feature.NullAsDefaultValue));
|
||||
assertEquals("{\"bean\":{},\"msg\":\"\"}", JSON.toJSONString(bean, JSONWriter.Feature.NullAsDefaultValue));
|
||||
}
|
||||
|
||||
@Data
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
package com.alibaba.fastjson2.issues_3500;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONWriter;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
||||
public class Issue3515 {
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
String jsonString = JSON.toJSONString(new Bean(), JSONWriter.Feature.NullAsDefaultValue);
|
||||
Bean bean = JSON.parseObject(jsonString, Bean.class);
|
||||
assertFalse(bean.getBoolVal());
|
||||
assertEquals((byte) 0, bean.getByteVal());
|
||||
assertEquals('\u0000', bean.getCharVal());
|
||||
assertEquals((short) 0, bean.getShortVal());
|
||||
assertEquals(0, bean.getIntVal());
|
||||
assertEquals(0L, bean.getLongVal());
|
||||
assertEquals(0.0F, bean.getFloatVal());
|
||||
assertEquals(0.0D, bean.getDoubleVal());
|
||||
assertEquals("", bean.getStringVal());
|
||||
assertEquals("{}", bean.getMapVal().toString());
|
||||
assertEquals("[]", bean.getListVal().toString());
|
||||
assertEquals(BigInteger.ZERO, bean.getIntegerVal());
|
||||
assertEquals(new BigDecimal("0.0"), bean.getDecimalVal());
|
||||
assertEquals("{}", bean.getObjectVal().toString());
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
static class Bean {
|
||||
private Boolean boolVal;
|
||||
private Byte byteVal;
|
||||
private Character charVal;
|
||||
private Short shortVal;
|
||||
private Integer intVal;
|
||||
private Long longVal;
|
||||
private Float floatVal;
|
||||
private Double doubleVal;
|
||||
private String stringVal;
|
||||
private Map<?, ?> mapVal;
|
||||
private List<?> listVal;
|
||||
private BigDecimal decimalVal;
|
||||
private BigInteger integerVal;
|
||||
private Object objectVal;
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@ public class Issue_20201016_01 {
|
|||
|
||||
String s = JSON.toJSONString(config, JSONWriter.Feature.WriteNulls, JSONWriter.Feature.NullAsDefaultValue);
|
||||
|
||||
assertEquals("{\"agent\":null,\"creator\":{\"account\":\"account\",\"name\":\"name\",\"workid\":\"\"},\"owner\":{\"account\":\"account\",\"name\":\"name\",\"workid\":\"\"}}", s);
|
||||
assertEquals("{\"agent\":{},\"creator\":{\"account\":\"account\",\"name\":\"name\",\"workid\":\"\"},\"owner\":{\"account\":\"account\",\"name\":\"name\",\"workid\":\"\"}}", s);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in New Issue