diff --git a/core/src/main/java/com/alibaba/fastjson2/JSON.java b/core/src/main/java/com/alibaba/fastjson2/JSON.java index 28f9bfeca8..244462cf5b 100644 --- a/core/src/main/java/com/alibaba/fastjson2/JSON.java +++ b/core/src/main/java/com/alibaba/fastjson2/JSON.java @@ -738,12 +738,22 @@ static List parseArray(byte[] bytes, Type type, JSONReader.Feature... fea * @param object Java Object to be serialized into JSON {@link String} */ static String toJSONString(Object object) { + return toJSONString(object, Boolean.FALSE); + } + + /** + * Serialize Java Object to JSON {@link String} + * + * @param object Java Object to be serialized into JSON {@link String} + * @param sort need to sort + */ + static String toJSONString(Object object, boolean sort) { try (JSONWriter writer = JSONWriter.of()) { if (object == null) { writer.writeNull(); } else { Class valueClass = object.getClass(); - ObjectWriter objectWriter = writer.getObjectWriter(valueClass, valueClass); + ObjectWriter objectWriter = writer.getObjectWriter(valueClass, valueClass, sort); objectWriter.write(writer, object, null, null, 0); } return writer.toString(); diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java index 8175f1cb2c..0afb20131d 100644 --- a/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java +++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java @@ -380,8 +380,12 @@ public ObjectWriter getObjectWriter(Class objectClass) { } public ObjectWriter getObjectWriter(Type objectType, Class objectClass) { + return this.getObjectWriter(objectType, objectClass, Boolean.FALSE); + } + + public ObjectWriter getObjectWriter(Type objectType, Class objectClass, boolean sort) { boolean fieldBased = (context.features & Feature.FieldBased.mask) != 0; - return context.provider.getObjectWriter(objectType, objectClass, fieldBased); + return context.provider.getObjectWriter(objectType, objectClass, fieldBased, sort); } public static JSONWriter of() { diff --git a/core/src/main/java/com/alibaba/fastjson2/writer/ObjectWriterCreator.java b/core/src/main/java/com/alibaba/fastjson2/writer/ObjectWriterCreator.java index afa04ec2e1..c3900e715f 100644 --- a/core/src/main/java/com/alibaba/fastjson2/writer/ObjectWriterCreator.java +++ b/core/src/main/java/com/alibaba/fastjson2/writer/ObjectWriterCreator.java @@ -41,7 +41,7 @@ public ObjectWriter createObjectWriter(Class objectType) { , 0 , JSONFactory .getDefaultObjectWriterProvider() - .getModules() + .getModules(), Boolean.FALSE ); } @@ -56,7 +56,7 @@ public ObjectWriter createObjectWriter( , FieldWriter... fieldWriters ) { if (fieldWriters.length == 0) { - return createObjectWriter(objectType, features, Collections.emptyList()); + return createObjectWriter(objectType, features, Collections.emptyList(), Boolean.FALSE); } else { return new ObjectWriterAdapter(objectType, features, fieldWriters); } @@ -146,6 +146,14 @@ public ObjectWriter createObjectWriter( Class objectClass , long features , final List modules + ) { + return this.createObjectWriter(objectClass, features, modules, Boolean.FALSE); + } + + public ObjectWriter createObjectWriter( + Class objectClass + , long features + , final List modules, boolean sort ) { BeanInfo beanInfo = new BeanInfo(); for (ObjectWriterModule module : modules) { @@ -184,7 +192,7 @@ public ObjectWriter createObjectWriter( if (fieldBased) { - Map fieldWriterMap = new TreeMap<>(); + Map fieldWriterMap = sort ? new LinkedHashMap<>() : new TreeMap<>(); BeanUtils.declaredFields(objectClass, field -> { if (Modifier.isTransient(field.getModifiers())) { return; @@ -207,7 +215,7 @@ public ObjectWriter createObjectWriter( } if (!fieldWritersCreated) { - Map fieldWriterMap = new TreeMap<>(); + Map fieldWriterMap = sort ? new LinkedHashMap<>() : new TreeMap<>(); BeanUtils.fields(objectClass, field -> { if (!Modifier.isPublic(field.getModifiers())) { @@ -309,8 +317,8 @@ public ObjectWriter createObjectWriter( } handleIgnores(beanInfo, fieldWriters); - - Collections.sort(fieldWriters); + if(sort) + Collections.sort(fieldWriters); ObjectWriterAdapter writerAdapter = new ObjectWriterAdapter(objectClass, beanInfo.typeKey, beanInfo.typeName, writerFeatures, fieldWriters); diff --git a/core/src/main/java/com/alibaba/fastjson2/writer/ObjectWriterCreatorASM.java b/core/src/main/java/com/alibaba/fastjson2/writer/ObjectWriterCreatorASM.java index 3ee299f427..fe1144669b 100644 --- a/core/src/main/java/com/alibaba/fastjson2/writer/ObjectWriterCreatorASM.java +++ b/core/src/main/java/com/alibaba/fastjson2/writer/ObjectWriterCreatorASM.java @@ -106,6 +106,15 @@ public ObjectWriter createObjectWriter( Class objectClass, long features, List modules + ) { + return this.createObjectWriter(objectClass, features, modules, false); + } + + @Override + public ObjectWriter createObjectWriter( + Class objectClass, + long features, + List modules, boolean sort ) { int modifiers = objectClass.getModifiers(); boolean externalClass = classLoader.isExternalClass(objectClass); @@ -113,7 +122,7 @@ public ObjectWriter createObjectWriter( if (!publicClass || externalClass) { if (!JDKUtils.UNSAFE_SUPPORT) { - return super.createObjectWriter(objectClass, features, modules); + return super.createObjectWriter(objectClass, features, modules, Boolean.FALSE); } } @@ -135,7 +144,7 @@ public ObjectWriter createObjectWriter( } if (beanInfo.serializeFilters != null && beanInfo.serializeFilters.length > 0) { - return super.createObjectWriter(objectClass, features, modules); + return super.createObjectWriter(objectClass, features, modules, Boolean.FALSE); } long writerFeatures = features | beanInfo.writerFeatures; @@ -145,14 +154,14 @@ public ObjectWriter createObjectWriter( } if (fieldBased && JDKUtils.JVM_VERSION >= 11 && !JDKUtils.LANG_UNNAMED && Throwable.class.isAssignableFrom(objectClass)) { - return super.createObjectWriter(objectClass, features, modules); + return super.createObjectWriter(objectClass, features, modules, Boolean.FALSE); } boolean record = BeanUtils.isRecord(objectClass); List fieldWriters; if (fieldBased && !record) { - Map fieldWriterMap = new TreeMap<>(); + Map fieldWriterMap = sort ? new TreeMap<>() : new LinkedHashMap<>(); final FieldInfo fieldInfo = new FieldInfo(); BeanUtils.declaredFields(objectClass, field -> { if (Modifier.isTransient(field.getModifiers())) { @@ -166,7 +175,7 @@ boolean record = BeanUtils.isRecord(objectClass); }); fieldWriters = new ArrayList<>(fieldWriterMap.values()); } else { - Map fieldWriterMap = new TreeMap<>(); + Map fieldWriterMap = sort ? new TreeMap<>() : new LinkedHashMap<>(); List fieldWriterList = new ArrayList<>(); boolean fieldWritersCreated = false; for (ObjectWriterModule module : modules) { @@ -180,7 +189,7 @@ boolean record = BeanUtils.isRecord(objectClass); for (FieldWriter fieldWriter : fieldWriterList) { Method method = fieldWriter.getMethod(); if (method == null) { - return super.createObjectWriter(objectClass, writerFeatures, modules); + return super.createObjectWriter(objectClass, writerFeatures, modules, Boolean.FALSE); } fieldWriterMap.putIfAbsent(fieldWriter.getFieldName(), fieldWriter); } @@ -286,7 +295,8 @@ boolean record = BeanUtils.isRecord(objectClass); } handleIgnores(beanInfo, fieldWriters); - Collections.sort(fieldWriters); + if(sort) + Collections.sort(fieldWriters); boolean match = true; if (fieldWriters.size() >= 100 || Throwable.class.isAssignableFrom(objectClass)) { @@ -307,7 +317,7 @@ boolean record = BeanUtils.isRecord(objectClass); } if (!match) { - return super.createObjectWriter(objectClass, writerFeatures, modules); + return super.createObjectWriter(objectClass, writerFeatures, modules, Boolean.FALSE); } ClassWriter cw = new ClassWriter(); diff --git a/core/src/main/java/com/alibaba/fastjson2/writer/ObjectWriterProvider.java b/core/src/main/java/com/alibaba/fastjson2/writer/ObjectWriterProvider.java index 7745dbb746..91b7c4c6a3 100644 --- a/core/src/main/java/com/alibaba/fastjson2/writer/ObjectWriterProvider.java +++ b/core/src/main/java/com/alibaba/fastjson2/writer/ObjectWriterProvider.java @@ -95,6 +95,10 @@ public ObjectWriter getObjectWriter(Type objectType, Class objectClass) { } public ObjectWriter getObjectWriter(Type objectType, Class objectClass, boolean fieldBased) { + return this.getObjectWriter(objectClass, objectClass, fieldBased, Boolean.FALSE); + } + + public ObjectWriter getObjectWriter(Type objectType, Class objectClass, boolean fieldBased, boolean sort) { ObjectWriter objectWriter = fieldBased ? cacheFieldBased.get(objectType) : cache.get(objectType); @@ -155,7 +159,7 @@ public ObjectWriter getObjectWriter(Type objectType, Class objectClass, boolean objectWriter = creator.createObjectWriter( objectClass, fieldBased ? JSONWriter.Feature.FieldBased.mask : 0 - , modules + , modules, sort ); ObjectWriter previous = fieldBased ? cacheFieldBased.putIfAbsent(objectType, objectWriter)