2.0.56.android4 release
This commit is contained in:
parent
50079d5ea7
commit
c6c7c92369
@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
<artifactId>fastjson2-parent</artifactId>
|
||||
<version>2.0.55.android5</version>
|
||||
<version>2.0.56.android5</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
<artifactId>fastjson2-parent</artifactId>
|
||||
<version>2.0.55.android5</version>
|
||||
<version>2.0.56.android5</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
<artifactId>fastjson2-parent</artifactId>
|
||||
<version>2.0.55.android5</version>
|
||||
<version>2.0.56.android5</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -32,7 +32,7 @@ public interface JSON {
|
||||
/**
|
||||
* fastjson2 version name
|
||||
*/
|
||||
String VERSION = "2.0.55";
|
||||
String VERSION = "2.0.56";
|
||||
|
||||
/**
|
||||
* Parses the json string as a {@link JSONArray} or {@link JSONObject}.
|
||||
|
@ -3794,6 +3794,7 @@ public abstract class JSONReader
|
||||
}
|
||||
}
|
||||
}
|
||||
protected static final long MASK_DISABLE_REFERENCE_DETECT = 1L << 33;
|
||||
|
||||
public enum Feature {
|
||||
FieldBased(1),
|
||||
@ -3917,7 +3918,12 @@ public abstract class JSONReader
|
||||
/**
|
||||
* @since 2.0.53
|
||||
*/
|
||||
UseDoubleForDecimals(1L << 32L);
|
||||
UseDoubleForDecimals(1L << 32L),
|
||||
|
||||
/**
|
||||
* @since 2.0.56
|
||||
*/
|
||||
DisableReferenceDetect(MASK_DISABLE_REFERENCE_DETECT);
|
||||
|
||||
public final long mask;
|
||||
|
||||
|
@ -154,8 +154,10 @@ final class JSONReaderUTF16
|
||||
return bytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isReference() {
|
||||
if ((context.features & MASK_DISABLE_REFERENCE_DETECT) != 0) {
|
||||
return false;
|
||||
}
|
||||
// should be codeSize <= FreqInlineSize 325, current is 276
|
||||
final char[] chars = this.chars;
|
||||
char ch = this.ch;
|
||||
@ -188,6 +190,11 @@ final class JSONReaderUTF16
|
||||
return false;
|
||||
}
|
||||
|
||||
return isReference0(chars, offset, end, quote);
|
||||
}
|
||||
|
||||
private boolean isReference0(char[] chars, int offset, int end, char quote) {
|
||||
char ch;
|
||||
offset += 6;
|
||||
ch = chars[offset];
|
||||
while (ch <= ' ' && ((1L << ch) & SPACE) != 0) {
|
||||
@ -211,7 +218,9 @@ final class JSONReaderUTF16
|
||||
ch = chars[offset];
|
||||
}
|
||||
|
||||
if (ch != quote || (offset + 1 < end && chars[offset + 1] == '#')) {
|
||||
if (ch != quote
|
||||
|| (offset + 1 < end && (ch = chars[offset + 1]) != '$' && ch != '.' && ch != '@')
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,8 @@ import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
class JSONReaderUTF8
|
||||
extends JSONReader {
|
||||
static final int REF = BIG_ENDIAN ? 0x24726566 : 0x66657224;
|
||||
|
||||
protected final byte[] bytes;
|
||||
protected final int length;
|
||||
protected final int start;
|
||||
@ -4683,8 +4685,11 @@ class JSONReaderUTF8
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReference() {
|
||||
public final boolean isReference() {
|
||||
// should be codeSize <= FreqInlineSize 325, current : 284
|
||||
if ((context.features & MASK_DISABLE_REFERENCE_DETECT) != 0) {
|
||||
return false;
|
||||
}
|
||||
final byte[] bytes = this.bytes;
|
||||
int ch = this.ch;
|
||||
if (ch != '{') {
|
||||
@ -4705,17 +4710,18 @@ class JSONReaderUTF8
|
||||
ch = bytes[offset];
|
||||
}
|
||||
|
||||
int quote = ch;
|
||||
if (offset + 6 >= end
|
||||
|| bytes[offset + 1] != '$'
|
||||
|| bytes[offset + 2] != 'r'
|
||||
|| bytes[offset + 3] != 'e'
|
||||
|| bytes[offset + 4] != 'f'
|
||||
|| bytes[offset + 5] != quote
|
||||
|| bytes[offset + 5] != ch
|
||||
|| UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET + offset + 1) != REF
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isReference0(bytes, offset, end, ch);
|
||||
}
|
||||
|
||||
private boolean isReference0(byte[] bytes, int offset, int end, int quote) {
|
||||
int ch;
|
||||
offset += 6;
|
||||
ch = bytes[offset];
|
||||
while (ch >= 0 && ch <= ' ' && ((1L << ch) & SPACE) != 0) {
|
||||
@ -4739,7 +4745,9 @@ class JSONReaderUTF8
|
||||
ch = bytes[offset];
|
||||
}
|
||||
|
||||
if (ch != quote || (offset + 1 < end && bytes[offset + 1] == '#')) {
|
||||
if (ch != quote
|
||||
|| (offset + 1 < end && (ch = bytes[offset + 1]) != '$' && ch != '.' && ch != '@')
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -121,4 +121,9 @@ public @interface JSONField {
|
||||
* @since 2.0.52
|
||||
*/
|
||||
Class<?> arrayToMapDuplicateHandler() default Void.class;
|
||||
|
||||
/**
|
||||
* @since 2.0.56
|
||||
*/
|
||||
Class<?> contentAs() default Void.class;
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ public class FieldInfo {
|
||||
public static final long DISABLE_REFERENCE_DETECT = 1L << 58;
|
||||
public static final long BACKR_EFERENCE = 1L << 61;
|
||||
public static final long RECORD = 1L << 62;
|
||||
public static final long CONTENT_AS = 1L << 63;
|
||||
|
||||
public String fieldName;
|
||||
public String format;
|
||||
@ -44,6 +45,11 @@ public class FieldInfo {
|
||||
public String arrayToMapKey;
|
||||
public Class<?> arrayToMapDuplicateHandler;
|
||||
|
||||
/**
|
||||
* @since 2.0.56
|
||||
*/
|
||||
public Class<?> contentAs;
|
||||
|
||||
public ObjectReader getInitReader() {
|
||||
Class<?> calzz = readUsing;
|
||||
if (calzz != null && ObjectReader.class.isAssignableFrom(calzz)) {
|
||||
@ -94,5 +100,6 @@ public class FieldInfo {
|
||||
|
||||
arrayToMapKey = null;
|
||||
arrayToMapDuplicateHandler = null;
|
||||
contentAs = null;
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ abstract class FieldWriterList<T>
|
||||
ObjectWriter listWriter;
|
||||
ObjectWriter itemObjectWriter;
|
||||
final boolean writeAsString;
|
||||
final Class<?> contentAs;
|
||||
|
||||
FieldWriterList(
|
||||
String name,
|
||||
@ -32,9 +33,11 @@ abstract class FieldWriterList<T>
|
||||
Type fieldType,
|
||||
Class fieldClass,
|
||||
Field field,
|
||||
Method method
|
||||
Method method,
|
||||
Class<?> contentAs
|
||||
) {
|
||||
super(name, ordinal, features, format, label, fieldType, fieldClass, field, method);
|
||||
this.contentAs = contentAs;
|
||||
|
||||
writeAsString = (features & WriteNonStringValueAsString.mask) != 0;
|
||||
|
||||
@ -74,6 +77,13 @@ abstract class FieldWriterList<T>
|
||||
|
||||
@Override
|
||||
public ObjectWriter getItemWriter(JSONWriter jsonWriter, Type itemType) {
|
||||
if (contentAs != null) {
|
||||
ObjectWriter itemObjectWriter = this.itemObjectWriter;
|
||||
if (itemObjectWriter != null) {
|
||||
return itemObjectWriter;
|
||||
}
|
||||
return this.itemObjectWriter = jsonWriter.getObjectWriter(this.contentAs, contentAs);
|
||||
}
|
||||
if (itemType == null || itemType == this.itemType) {
|
||||
if (itemObjectWriter != null) {
|
||||
return itemObjectWriter;
|
||||
|
@ -19,9 +19,10 @@ final class FieldWriterListField<T>
|
||||
String label,
|
||||
Type fieldType,
|
||||
Class fieldClass,
|
||||
Field field
|
||||
Field field,
|
||||
Class<?> contentAs
|
||||
) {
|
||||
super(fieldName, itemType, ordinal, features, format, label, fieldType, fieldClass, field, null);
|
||||
super(fieldName, itemType, ordinal, features, format, label, fieldType, fieldClass, field, null, contentAs);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -23,9 +23,10 @@ final class FieldWriterListFunc<T>
|
||||
Method method,
|
||||
Function<T, List> function,
|
||||
Type fieldType,
|
||||
Class fieldClass
|
||||
Class fieldClass,
|
||||
Class<?> contentAs
|
||||
) {
|
||||
super(fieldName, itemType, ordinal, features, format, label, fieldType, fieldClass, null, method);
|
||||
super(fieldName, itemType, ordinal, features, format, label, fieldType, fieldClass, null, method, contentAs);
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
|
@ -23,9 +23,10 @@ final class FieldWriterListMethod<T>
|
||||
Field field,
|
||||
Method method,
|
||||
Type fieldType,
|
||||
Class fieldClass
|
||||
Class fieldClass,
|
||||
Class<?> contentAs
|
||||
) {
|
||||
super(fieldName, itemType, ordinal, features, format, label, fieldType, fieldClass, field, method);
|
||||
super(fieldName, itemType, ordinal, features, format, label, fieldType, fieldClass, field, method, contentAs);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,86 @@
|
||||
package com.alibaba.fastjson2.writer;
|
||||
|
||||
import com.alibaba.fastjson2.JSONWriter;
|
||||
import com.alibaba.fastjson2.codec.FieldInfo;
|
||||
import com.alibaba.fastjson2.util.ParameterizedTypeImpl;
|
||||
import com.alibaba.fastjson2.util.TypeUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
abstract class FieldWriterMap
|
||||
extends FieldWriterObject {
|
||||
protected final Class<?> contentAs;
|
||||
protected Type contentAsFieldType;
|
||||
volatile ObjectWriter mapWriter;
|
||||
private final Type keyType;
|
||||
private final Type valueType;
|
||||
final boolean valueTypeRefDetect;
|
||||
volatile ObjectWriter valueWriter;
|
||||
|
||||
protected FieldWriterMap(
|
||||
String name,
|
||||
int ordinal,
|
||||
long features,
|
||||
String format,
|
||||
String label,
|
||||
Type fieldType,
|
||||
Class fieldClass,
|
||||
Field field,
|
||||
Method method,
|
||||
Class<?> contentAs
|
||||
) {
|
||||
super(name, ordinal, features, format, label, fieldType, fieldClass, field, method);
|
||||
Type keyType = null, valueType = null;
|
||||
Type contentAsFieldType = null;
|
||||
if (fieldType instanceof ParameterizedType) {
|
||||
ParameterizedType pt = (ParameterizedType) fieldType;
|
||||
Type[] actualTypeArguments = pt.getActualTypeArguments();
|
||||
if (actualTypeArguments.length == 2) {
|
||||
keyType = actualTypeArguments[0];
|
||||
valueType = actualTypeArguments[1];
|
||||
}
|
||||
}
|
||||
if (keyType == null) {
|
||||
keyType = Object.class;
|
||||
}
|
||||
if (valueType == null) {
|
||||
valueType = Object.class;
|
||||
}
|
||||
if (contentAs != null) {
|
||||
contentAsFieldType = new ParameterizedTypeImpl(fieldClass, String.class, contentAs);
|
||||
}
|
||||
this.contentAs = contentAs;
|
||||
this.contentAsFieldType = contentAsFieldType;
|
||||
this.keyType = keyType;
|
||||
this.valueType = valueType;
|
||||
this.valueTypeRefDetect = !ObjectWriterProvider.isNotReferenceDetect(TypeUtils.getClass(valueType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectWriter getObjectWriter(JSONWriter jsonWriter, Class valueClass) {
|
||||
Class<?> contentAs = this.contentAs;
|
||||
if (contentAs == null || !fieldClass.isAssignableFrom(valueClass)) {
|
||||
return super.getObjectWriter(jsonWriter, valueClass);
|
||||
}
|
||||
|
||||
ObjectWriter valueWriter = this.valueWriter;
|
||||
if (valueWriter != null) {
|
||||
return valueWriter;
|
||||
}
|
||||
|
||||
Type fieldType = this.fieldType;
|
||||
Type valueType = this.valueType;
|
||||
long features = this.features;
|
||||
if (contentAs != null) {
|
||||
valueType = contentAs;
|
||||
fieldType = contentAsFieldType;
|
||||
features |= FieldInfo.CONTENT_AS;
|
||||
}
|
||||
valueWriter = new ObjectWriterImplMap(keyType, valueType, valueClass, fieldType, features);
|
||||
this.mapWriter = valueWriter;
|
||||
return valueWriter;
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package com.alibaba.fastjson2.writer;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
final class FieldWriterMapField
|
||||
extends FieldWriterMap {
|
||||
FieldWriterMapField(
|
||||
String name,
|
||||
int ordinal,
|
||||
long features,
|
||||
String format,
|
||||
String label,
|
||||
Type fieldType,
|
||||
Class fieldClass,
|
||||
Field field,
|
||||
Method method,
|
||||
Class<?> contentAs
|
||||
) {
|
||||
super(name, ordinal, features, format, label, fieldType, fieldClass, field, method, contentAs);
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.alibaba.fastjson2.writer;
|
||||
|
||||
import com.alibaba.fastjson2.function.Function;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
final class FieldWriterMapFunction
|
||||
extends FieldWriterMap {
|
||||
final Function function;
|
||||
FieldWriterMapFunction(
|
||||
String name,
|
||||
int ordinal,
|
||||
long features,
|
||||
String format,
|
||||
String label,
|
||||
Type fieldType,
|
||||
Class fieldClass,
|
||||
Field field,
|
||||
Method method,
|
||||
Function function,
|
||||
Class<?> contentAs
|
||||
) {
|
||||
super(name, ordinal, features, format, label, fieldType, fieldClass, field, method, contentAs);
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getFieldValue(Object object) {
|
||||
return function.apply(object);
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package com.alibaba.fastjson2.writer;
|
||||
|
||||
import com.alibaba.fastjson2.JSONException;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
final class FieldWriterMapMethod
|
||||
extends FieldWriterMap {
|
||||
FieldWriterMapMethod(
|
||||
String name,
|
||||
int ordinal,
|
||||
long features,
|
||||
String format,
|
||||
String label,
|
||||
Type fieldType,
|
||||
Class fieldClass,
|
||||
Field field,
|
||||
Method method,
|
||||
Class<?> contentAs
|
||||
) {
|
||||
super(name, ordinal, features, format, label, fieldType, fieldClass, field, method, contentAs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getFieldValue(Object object) {
|
||||
try {
|
||||
return method.invoke(object);
|
||||
} catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) {
|
||||
throw new JSONException("invoke getter method error, " + fieldName, e);
|
||||
}
|
||||
}
|
||||
}
|
@ -223,7 +223,7 @@ public class ObjectWriterCreator {
|
||||
format = beanInfo.format;
|
||||
}
|
||||
|
||||
return createFieldWriter(provider, fieldName, fieldInfo.ordinal, fieldInfo.features, format, fieldInfo.label, field, writeUsingWriter);
|
||||
return createFieldWriter(provider, fieldName, fieldInfo.ordinal, fieldInfo.features, format, fieldInfo.label, field, writeUsingWriter, fieldInfo.contentAs);
|
||||
}
|
||||
|
||||
public ObjectWriter createObjectWriter(
|
||||
@ -362,7 +362,8 @@ public class ObjectWriterCreator {
|
||||
fieldInfo.format,
|
||||
fieldInfo.label,
|
||||
method,
|
||||
writeUsingWriter
|
||||
writeUsingWriter,
|
||||
fieldInfo.contentAs
|
||||
);
|
||||
|
||||
FieldWriter origin = fieldWriterMap.get(fieldWriter.fieldName);
|
||||
@ -574,6 +575,20 @@ public class ObjectWriterCreator {
|
||||
String label,
|
||||
Field field,
|
||||
ObjectWriter initObjectWriter
|
||||
) {
|
||||
return createFieldWriter(provider, fieldName, ordinal, features, format, label, field, initObjectWriter, null);
|
||||
}
|
||||
|
||||
public <T> FieldWriter<T> createFieldWriter(
|
||||
ObjectWriterProvider provider,
|
||||
String fieldName,
|
||||
int ordinal,
|
||||
long features,
|
||||
String format,
|
||||
String label,
|
||||
Field field,
|
||||
ObjectWriter initObjectWriter,
|
||||
Class<?> contentAs
|
||||
) {
|
||||
Class<?> declaringClass = field.getDeclaringClass();
|
||||
Method method = null;
|
||||
@ -701,7 +716,11 @@ public class ObjectWriterCreator {
|
||||
if (fieldType instanceof ParameterizedType) {
|
||||
itemType = ((ParameterizedType) fieldType).getActualTypeArguments()[0];
|
||||
}
|
||||
return new FieldWriterListField(fieldName, itemType, ordinal, features, format, label, fieldType, fieldClass, field);
|
||||
return new FieldWriterListField(fieldName, itemType, ordinal, features, format, label, fieldType, fieldClass, field, contentAs);
|
||||
}
|
||||
|
||||
if (Map.class.isAssignableFrom(fieldClass)) {
|
||||
return new FieldWriterMapField(fieldName, ordinal, features, format, label, field.getGenericType(), fieldClass, field, null, contentAs);
|
||||
}
|
||||
|
||||
if (fieldClass.isArray() && !fieldClass.getComponentType().isPrimitive()) {
|
||||
@ -739,6 +758,21 @@ public class ObjectWriterCreator {
|
||||
String label,
|
||||
Method method,
|
||||
ObjectWriter initObjectWriter
|
||||
) {
|
||||
return createFieldWriter(provider, objectType, fieldName, ordinal, features, format, label, method, initObjectWriter, null);
|
||||
}
|
||||
|
||||
public <T> FieldWriter<T> createFieldWriter(
|
||||
ObjectWriterProvider provider,
|
||||
Class<T> objectType,
|
||||
String fieldName,
|
||||
int ordinal,
|
||||
long features,
|
||||
String format,
|
||||
String label,
|
||||
Method method,
|
||||
ObjectWriter initObjectWriter,
|
||||
Class<?> contentAs
|
||||
) {
|
||||
Class<?> fieldClass = method.getReturnType();
|
||||
Type fieldType = method.getGenericReturnType();
|
||||
@ -848,7 +882,11 @@ public class ObjectWriterCreator {
|
||||
} else {
|
||||
itemType = Object.class;
|
||||
}
|
||||
return new FieldWriterListMethod(fieldName, itemType, ordinal, features, format, label, field, method, fieldType, fieldClass);
|
||||
return new FieldWriterListMethod(fieldName, itemType, ordinal, features, format, label, field, method, fieldType, fieldClass, contentAs);
|
||||
}
|
||||
|
||||
if (Map.class.isAssignableFrom(fieldClass)) {
|
||||
return new FieldWriterMapMethod(fieldName, ordinal, features, format, label, fieldType, fieldClass, field, method, contentAs);
|
||||
}
|
||||
|
||||
if (fieldClass == Float[].class) {
|
||||
@ -933,6 +971,23 @@ public class ObjectWriterCreator {
|
||||
Class<V> fieldClass,
|
||||
Method method,
|
||||
Function<T, V> function
|
||||
) {
|
||||
return createFieldWriter(provider, objectClass, fieldName, ordinal, features, format, label, fieldType, fieldClass, method, function, null);
|
||||
}
|
||||
|
||||
public <T, V> FieldWriter<T> createFieldWriter(
|
||||
ObjectWriterProvider provider,
|
||||
Class<T> objectClass,
|
||||
String fieldName,
|
||||
int ordinal,
|
||||
long features,
|
||||
String format,
|
||||
String label,
|
||||
Type fieldType,
|
||||
Class<V> fieldClass,
|
||||
Method method,
|
||||
Function<T, V> function,
|
||||
Class<?> contentAs
|
||||
) {
|
||||
if (fieldClass == Byte.class) {
|
||||
return new FieldWriterInt8Func(fieldName, ordinal, features, format, label, method, function);
|
||||
@ -1008,9 +1063,13 @@ public class ObjectWriterCreator {
|
||||
if (itemType == String.class) {
|
||||
return new FieldWriterListStrFunc(fieldName, ordinal, features, format, label, method, function, fieldType, fieldClass);
|
||||
}
|
||||
return new FieldWriterListFunc(fieldName, ordinal, features, format, label, itemType, method, function, fieldType, fieldClass);
|
||||
return new FieldWriterListFunc(fieldName, ordinal, features, format, label, itemType, method, function, fieldType, fieldClass, contentAs);
|
||||
}
|
||||
}
|
||||
|
||||
if (rawType instanceof Class && Map.class.isAssignableFrom((Class<?>) rawType)) {
|
||||
return new FieldWriterMapFunction(fieldName, ordinal, features, format, label, fieldType, fieldClass, null, method, function, contentAs);
|
||||
}
|
||||
}
|
||||
|
||||
if (Modifier.isFinal(fieldClass.getModifiers())) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.alibaba.fastjson2.writer;
|
||||
|
||||
import com.alibaba.fastjson2.*;
|
||||
import com.alibaba.fastjson2.codec.FieldInfo;
|
||||
import com.alibaba.fastjson2.filter.*;
|
||||
import com.alibaba.fastjson2.util.*;
|
||||
|
||||
@ -43,6 +44,8 @@ public final class ObjectWriterImplMap
|
||||
final char[] typeInfoUTF16;
|
||||
final byte[] typeInfoUTF8;
|
||||
|
||||
final boolean contentAs;
|
||||
|
||||
public ObjectWriterImplMap(Class objectClass, long features) {
|
||||
this(null, null, objectClass, objectClass, features);
|
||||
}
|
||||
@ -59,6 +62,7 @@ public final class ObjectWriterImplMap
|
||||
} else {
|
||||
this.valueTypeRefDetect = !ObjectWriterProvider.isNotReferenceDetect(TypeUtils.getClass(valueType));
|
||||
}
|
||||
contentAs = (features & FieldInfo.CONTENT_AS) != 0;
|
||||
|
||||
String typeName = TypeUtils.getTypeName(objectClass);
|
||||
String typeInfoStr = "\"@type\":\"" + objectClass.getName() + "\"";
|
||||
@ -148,7 +152,12 @@ public final class ObjectWriterImplMap
|
||||
|
||||
jsonWriter.writeString(key);
|
||||
|
||||
Class<?> valueType = value.getClass();
|
||||
Class valueType;
|
||||
if (contentAs) {
|
||||
valueType = (Class) this.valueType;
|
||||
} else {
|
||||
valueType = value.getClass();
|
||||
}
|
||||
if (valueType == String.class) {
|
||||
jsonWriter.writeString((String) value);
|
||||
} else {
|
||||
@ -279,7 +288,12 @@ public final class ObjectWriterImplMap
|
||||
}
|
||||
}
|
||||
|
||||
Class<?> valueClass = value.getClass();
|
||||
Class valueClass;
|
||||
if (contentAs) {
|
||||
valueClass = (Class) this.valueType;
|
||||
} else {
|
||||
valueClass = value.getClass();
|
||||
}
|
||||
if (valueClass == String.class) {
|
||||
jsonWriter.writeString((String) value);
|
||||
continue;
|
||||
@ -480,7 +494,12 @@ public final class ObjectWriterImplMap
|
||||
}
|
||||
jsonWriter.writeColon();
|
||||
|
||||
Class<?> valueClass = value.getClass();
|
||||
Class valueClass;
|
||||
if (contentAs) {
|
||||
valueClass = (Class) this.valueType;
|
||||
} else {
|
||||
valueClass = value.getClass();
|
||||
}
|
||||
if (valueClass == String.class) {
|
||||
jsonWriter.writeString((String) value);
|
||||
continue;
|
||||
@ -654,7 +673,12 @@ public final class ObjectWriterImplMap
|
||||
if (value == null) {
|
||||
jsonWriter.writeNull();
|
||||
} else {
|
||||
Class<?> valueType = value.getClass();
|
||||
Class valueType;
|
||||
if (contentAs) {
|
||||
valueType = (Class) this.valueType;
|
||||
} else {
|
||||
valueType = value.getClass();
|
||||
}
|
||||
ObjectWriter valueWriter = jsonWriter.getObjectWriter(valueType);
|
||||
valueWriter.write(jsonWriter, value, fieldName, fieldType, this.features);
|
||||
}
|
||||
|
@ -634,6 +634,11 @@ public class ObjectWriterProvider {
|
||||
) {
|
||||
fieldInfo.writeUsing = ObjectWriterImplToString.class;
|
||||
}
|
||||
|
||||
Class<?> contentAs = jsonField.contentAs();
|
||||
if (contentAs != Void.class) {
|
||||
fieldInfo.contentAs = contentAs;
|
||||
}
|
||||
}
|
||||
|
||||
private void processJSONField1x(FieldInfo fieldInfo, Annotation annotation) {
|
||||
|
@ -0,0 +1,111 @@
|
||||
package com.alibaba.fastjson2.features;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class ContentAsTest {
|
||||
class Vehicle {
|
||||
private String type;
|
||||
|
||||
public Vehicle(String type) { this.type = type; }
|
||||
public String getType() { return type; }
|
||||
}
|
||||
|
||||
class Car
|
||||
extends Vehicle {
|
||||
private int seats;
|
||||
|
||||
public Car(String type, int seats) {
|
||||
super(type);
|
||||
this.seats = seats;
|
||||
}
|
||||
public int getSeats() { return seats; }
|
||||
}
|
||||
|
||||
class Garage {
|
||||
@JSONField(contentAs = Vehicle.class)
|
||||
private List<Vehicle> vehicles = new ArrayList<>();
|
||||
|
||||
public void addVehicle(Vehicle v) { vehicles.add(v); }
|
||||
public List<Vehicle> getVehicles() { return vehicles; }
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
Garage garage = new Garage();
|
||||
garage.addVehicle(new Car("Sedan", 5));
|
||||
garage.addVehicle(new Car("SUV", 7));
|
||||
|
||||
assertEquals(
|
||||
"{\"vehicles\":[{\"type\":\"Sedan\"},{\"type\":\"SUV\"}]}",
|
||||
JSON.toJSONString(garage));
|
||||
}
|
||||
|
||||
class GarageField {
|
||||
@JSONField(contentAs = Vehicle.class)
|
||||
public List<Vehicle> vehicles = new ArrayList<>();
|
||||
|
||||
public void addVehicle(Vehicle v) { vehicles.add(v); }
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testField() throws Exception {
|
||||
GarageField garage = new GarageField();
|
||||
garage.addVehicle(new Car("Sedan", 5));
|
||||
garage.addVehicle(new Car("SUV", 7));
|
||||
|
||||
assertEquals(
|
||||
"{\"vehicles\":[{\"type\":\"Sedan\"},{\"type\":\"SUV\"}]}",
|
||||
JSON.toJSONString(garage));
|
||||
}
|
||||
|
||||
class GarageMap {
|
||||
@JSONField(contentAs = Vehicle.class)
|
||||
private Map<String, Vehicle> vehicles = new LinkedHashMap<>();
|
||||
|
||||
public void addVehicle(Vehicle v) {
|
||||
vehicles.put(v.getType(), v);
|
||||
}
|
||||
|
||||
public Map<String, Vehicle> getVehicles() {
|
||||
return vehicles;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMap() throws Exception {
|
||||
GarageMap garage = new GarageMap();
|
||||
garage.addVehicle(new Car("Sedan", 5));
|
||||
garage.addVehicle(new Car("SUV", 7));
|
||||
|
||||
String json = JSON.toJSONString(garage);
|
||||
assertEquals("{\"vehicles\":{\"Sedan\":{\"type\":\"Sedan\"},\"SUV\":{\"type\":\"SUV\"}}}", json);
|
||||
}
|
||||
|
||||
class GarageMapField {
|
||||
@JSONField(contentAs = Vehicle.class)
|
||||
public Map<String, Vehicle> vehicles = new LinkedHashMap<>();
|
||||
|
||||
public void addVehicle(Vehicle v) {
|
||||
vehicles.put(v.getType(), v);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMapField() throws Exception {
|
||||
GarageMapField garage = new GarageMapField();
|
||||
garage.addVehicle(new Car("Sedan", 5));
|
||||
garage.addVehicle(new Car("SUV", 7));
|
||||
|
||||
String json = JSON.toJSONString(garage);
|
||||
assertEquals("{\"vehicles\":{\"Sedan\":{\"type\":\"Sedan\"},\"SUV\":{\"type\":\"SUV\"}}}", json);
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package com.alibaba.fastjson2.issues_3300;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.alibaba.fastjson2.JSONReader;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class Issue3347 {
|
||||
@Test
|
||||
public void test() {
|
||||
String json2 = "{\"*/*\":{\"schema\":{\"$ref\":\"Error-ModelName{namespace='javax.servlet.http', name='HttpServletResponse'}\"}}}";
|
||||
String expected = "Error-ModelName{namespace='javax.servlet.http', name='HttpServletResponse'}";
|
||||
{
|
||||
JSONObject jsonObject4 = JSON.parseObject(json2);
|
||||
assertEquals(expected, jsonObject4.getJSONObject("*/*").getJSONObject("schema").getString("$ref"));
|
||||
}
|
||||
{
|
||||
JSONObject jsonObject4 = JSON.parseObject(json2.getBytes(StandardCharsets.UTF_8));
|
||||
assertEquals(expected, jsonObject4.getJSONObject("*/*").getJSONObject("schema").getString("$ref"));
|
||||
}
|
||||
{
|
||||
JSONObject jsonObject4 = JSON.parseObject(json2.toCharArray());
|
||||
assertEquals(expected, jsonObject4.getJSONObject("*/*").getJSONObject("schema").getString("$ref"));
|
||||
}
|
||||
{
|
||||
JSONObject jsonObject4 = JSON.parseObject(json2, JSONReader.Feature.DisableReferenceDetect);
|
||||
assertEquals(expected, jsonObject4.getJSONObject("*/*").getJSONObject("schema").getString("$ref"));
|
||||
}
|
||||
}
|
||||
}
|
2
pom.xml
2
pom.xml
@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
<artifactId>fastjson2-parent</artifactId>
|
||||
<version>2.0.55.android5</version>
|
||||
<version>2.0.56.android5</version>
|
||||
<name>${project.artifactId}</name>
|
||||
<description>Fastjson is a JSON processor (JSON parser + JSON generator) written in Java</description>
|
||||
<packaging>pom</packaging>
|
||||
|
Loading…
x
Reference in New Issue
Block a user