@@ -336,17 +336,14 @@ protected void collectAll()
336
336
_renameUsing (props , naming );
337
337
}
338
338
339
- /* Sort by visibility (explicit over implicit); drop all but first
340
- * of member type (getter, setter etc) if there is visibility
341
- * difference
342
- */
339
+ // Sort by visibility (explicit over implicit); drop all but first of member
340
+ // type (getter, setter etc) if there is visibility difference
343
341
for (POJOPropertyBuilder property : props .values ()) {
344
342
property .trimByVisibility ();
345
343
}
346
344
347
- /* and, if required, apply wrapper name: note, MUST be done after
348
- * annotations are merged.
349
- */
345
+ // and, if required, apply wrapper name: note, MUST be done after
346
+ // annotations are merged.
350
347
if (_config .isEnabled (MapperFeature .USE_WRAPPER_NAME_AS_PROPERTY_NAME )) {
351
348
_renameWithWrappers (props );
352
349
}
@@ -933,25 +930,24 @@ protected void _renameWithWrappers(Map<String, POJOPropertyBuilder> props)
933
930
/**********************************************************
934
931
*/
935
932
936
- /* First, order by [JACKSON-90] (explicit ordering and/or alphabetic)
937
- * and then for [JACKSON-170] (implicitly order creator properties before others)
938
- */
933
+ // First, order by(explicit ordering and/or alphabetic),
934
+ // then by (optional) index (if any)
935
+ // and then implicitly order creator properties before others)
936
+
939
937
protected void _sortProperties (Map <String , POJOPropertyBuilder > props )
940
938
{
941
939
// Then how about explicit ordering?
942
- AnnotationIntrospector intr = _annotationIntrospector ;
940
+ final AnnotationIntrospector intr = _annotationIntrospector ;
943
941
Boolean alpha = intr .findSerializationSortAlphabetically ((Annotated ) _classDef );
944
- boolean sort ;
945
-
946
- if (alpha == null ) {
947
- sort = _config .shouldSortPropertiesAlphabetically ();
948
- } else {
949
- sort = alpha .booleanValue ();
950
- }
942
+ final boolean sort = (alpha == null )
943
+ ? _config .shouldSortPropertiesAlphabetically ()
944
+ : alpha .booleanValue ();
945
+ final boolean indexed = _anyIndexed (props .values ());
946
+
951
947
String [] propertyOrder = intr .findSerializationPropertyOrder (_classDef );
952
948
953
949
// no sorting? no need to shuffle, then
954
- if (!sort && (_creatorProperties == null ) && (propertyOrder == null )) {
950
+ if (!sort && ! indexed && (_creatorProperties == null ) && (propertyOrder == null )) {
955
951
return ;
956
952
}
957
953
int size = props .size ();
@@ -966,11 +962,11 @@ protected void _sortProperties(Map<String, POJOPropertyBuilder> props)
966
962
for (POJOPropertyBuilder prop : props .values ()) {
967
963
all .put (prop .getName (), prop );
968
964
}
969
- Map <String ,POJOPropertyBuilder > ordered = new LinkedHashMap <String , POJOPropertyBuilder >(size +size );
965
+ Map <String ,POJOPropertyBuilder > ordered = new LinkedHashMap <>(size +size );
970
966
// Ok: primarily by explicit order
971
967
if (propertyOrder != null ) {
972
968
for (String name : propertyOrder ) {
973
- POJOPropertyBuilder w = all .get (name );
969
+ POJOPropertyBuilder w = all .remove (name );
974
970
if (w == null ) { // will also allow use of "implicit" names for sorting
975
971
for (POJOPropertyBuilder prop : props .values ()) {
976
972
if (name .equals (prop .getInternalName ())) {
@@ -986,7 +982,26 @@ protected void _sortProperties(Map<String, POJOPropertyBuilder> props)
986
982
}
987
983
}
988
984
}
989
- // And secondly by sorting Creator properties before other unordered properties
985
+
986
+ // Second (starting with 2.11): index, if any:
987
+ if (indexed ) {
988
+ Map <Integer ,POJOPropertyBuilder > byIndex = new TreeMap <>();
989
+ Iterator <Map .Entry <String ,POJOPropertyBuilder >> it = all .entrySet ().iterator ();
990
+ while (it .hasNext ()) {
991
+ Map .Entry <String ,POJOPropertyBuilder > entry = it .next ();
992
+ POJOPropertyBuilder prop = entry .getValue ();
993
+ Integer index = prop .getMetadata ().getIndex ();
994
+ if (index != null ) {
995
+ byIndex .put (index , prop );
996
+ it .remove ();
997
+ }
998
+ }
999
+ for (POJOPropertyBuilder prop : byIndex .values ()) {
1000
+ ordered .put (prop .getName (), prop );
1001
+ }
1002
+ }
1003
+
1004
+ // Third by sorting Creator properties before other unordered properties
990
1005
if (_creatorProperties != null ) {
991
1006
/* As per [databind#311], this is bit delicate; but if alphabetic ordering
992
1007
* is mandated, at least ensure creator properties are in alphabetic
@@ -1008,6 +1023,8 @@ protected void _sortProperties(Map<String, POJOPropertyBuilder> props)
1008
1023
// 16-Jan-2016, tatu: Related to [databind#1317], make sure not to accidentally
1009
1024
// add back pruned creator properties!
1010
1025
String name = prop .getName ();
1026
+ // 27-Nov-2019, tatu: Not sure why, but we should NOT remove it from `all` tho:
1027
+ // if (all.remove(name) != null) {
1011
1028
if (all .containsKey (name )) {
1012
1029
ordered .put (name , prop );
1013
1030
}
@@ -1017,7 +1034,16 @@ protected void _sortProperties(Map<String, POJOPropertyBuilder> props)
1017
1034
ordered .putAll (all );
1018
1035
props .clear ();
1019
1036
props .putAll (ordered );
1020
- }
1037
+ }
1038
+
1039
+ private boolean _anyIndexed (Collection <POJOPropertyBuilder > props ) {
1040
+ for (POJOPropertyBuilder prop : props ) {
1041
+ if (prop .getMetadata ().hasIndex ()) {
1042
+ return true ;
1043
+ }
1044
+ }
1045
+ return false ;
1046
+ }
1021
1047
1022
1048
/*
1023
1049
/**********************************************************
0 commit comments