2.0.56.android8 release

This commit is contained in:
高铁 2025-02-22 08:20:50 +08:00
parent dbfd35f30f
commit f7888afc8e
23 changed files with 503 additions and 51 deletions

View File

@ -6,7 +6,7 @@
<parent>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2-parent</artifactId>
<version>2.0.55.android8</version>
<version>2.0.56.android8</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2-parent</artifactId>
<version>2.0.55.android8</version>
<version>2.0.56.android8</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2-parent</artifactId>
<version>2.0.55.android8</version>
<version>2.0.56.android8</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -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}.

View File

@ -3852,6 +3852,8 @@ public abstract class JSONReader
}
}
protected static final long MASK_DISABLE_REFERENCE_DETECT = 1L << 33;
public enum Feature {
FieldBased(1),
IgnoreNoneSerializable(1 << 1),
@ -3974,7 +3976,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;

View File

@ -155,17 +155,18 @@ final class JSONReaderUTF16
return bytes;
}
@Override
public boolean isReference() {
// should be codeSize <= FreqInlineSize 325
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;
int offset = this.offset;
if (ch != '{') {
return false;
}
int offset = this.offset, end = this.end;
if (offset == end) {
return false;
}
@ -180,20 +181,21 @@ final class JSONReaderUTF16
}
char quote = ch;
if (quote != '"' && quote != '\'' || this.offset + 5 >= end) {
return false;
}
if (chars[offset + 1] != '$'
if (offset + 6 >= end
|| chars[offset + 1] != '$'
|| chars[offset + 2] != 'r'
|| chars[offset + 3] != 'e'
|| chars[offset + 4] != 'f'
|| chars[offset + 5] != quote
|| offset + 6 >= end
) {
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) {
@ -217,7 +219,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;
}

View File

@ -17,6 +17,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;
@ -4950,22 +4952,24 @@ class JSONReaderUTF8
}
@Override
public boolean isReference() {
// should be codeSize <= FreqInlineSize 325
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;
int offset = this.offset;
if (ch != '{') {
return false;
}
int offset = this.offset, end = this.end;
if (offset == end) {
return false;
}
ch = bytes[offset];
while (ch >= 0 && ch <= ' ' && ((1L << ch) & SPACE) != 0) {
while (ch <= ' ' && ((1L << ch) & SPACE) != 0) {
offset++;
if (offset >= end) {
return false;
@ -4973,23 +4977,23 @@ class JSONReaderUTF8
ch = bytes[offset];
}
int quote = ch;
if ((quote != '"' && quote != '\'')
|| this.offset + 5 >= end
|| (bytes[offset + 1] != '$'
|| bytes[offset + 2] != 'r'
|| bytes[offset + 3] != 'e'
|| bytes[offset + 4] != 'f'
|| bytes[offset + 5] != quote
|| offset + 6 >= end)
if (offset + 6 >= end
|| 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) {
if (++offset >= end) {
offset++;
if (offset >= end) {
return false;
}
ch = bytes[offset];
@ -5001,13 +5005,16 @@ class JSONReaderUTF8
ch = bytes[++offset];
while (ch >= 0 && ch <= ' ' && ((1L << ch) & SPACE) != 0) {
if (++offset >= end) {
offset++;
if (offset >= end) {
return false;
}
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;
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1,32 @@
package com.alibaba.fastjson2.writer;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.function.Function;
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);
}
}

View File

@ -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);
}
}
}

View File

@ -224,7 +224,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(
@ -363,7 +363,8 @@ public class ObjectWriterCreator {
fieldInfo.format,
fieldInfo.label,
method,
writeUsingWriter
writeUsingWriter,
fieldInfo.contentAs
);
FieldWriter origin = fieldWriterMap.get(fieldWriter.fieldName);
@ -575,6 +576,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;
@ -702,7 +717,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()) {
@ -740,6 +759,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();
@ -849,7 +883,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) {
@ -934,6 +972,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);
@ -1009,9 +1064,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())) {

View File

@ -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);
}

View File

@ -623,6 +623,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) {

View File

@ -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);
}
}

View File

@ -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"));
}
}
}

View File

@ -6,7 +6,7 @@
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2-parent</artifactId>
<version>2.0.55.android8</version>
<version>2.0.56.android8</version>
<name>${project.artifactId}</name>
<description>Fastjson is a JSON processor (JSON parser + JSON generator) written in Java</description>
<packaging>pom</packaging>