Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/main/java/com/fasterxml/jackson/databind/MapperFeature.java
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,20 @@ public enum MapperFeature implements ConfigFeature
*/
SORT_PROPERTIES_ALPHABETICALLY(false),

/**
* Feature that enforces strict ordering as requested by other configuration methods
* for POJO fields (note: does <b>not</b> apply to {@link java.util.Map}
* serialization!):
* if enabled, ordering is preserved even if {@link com.fasterxml.jackson.annotation.JsonCreator}
* is present. Without this feature properties referenced by {@link com.fasterxml.jackson.annotation.JsonCreator}
* taking precedence over other properties even if sorting is requested.
*<p>
* Note that if ordering is not enabled using other ways, this feature has no effect.
*<p>
* Feature is disabled by default.
*/
STRICT_PROPERTIES_ORDERING(false),

/*
/******************************************************
/* Name-related features
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,14 @@ public final boolean shouldSortPropertiesAlphabetically() {
return isEnabled(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
}

/**
* Accessor for checking whether default settings for forcing property
* ordering is enabled.
*/
public final boolean shouldPreservePropertiesOrdering() {
return isEnabled(MapperFeature.STRICT_PROPERTIES_ORDERING);
}

/**
* Accessor for checking whether configuration indicates that
* "root wrapping" (use of an extra property/name pair at root level)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1115,7 +1115,8 @@ protected void _sortProperties(Map<String, POJOPropertyBuilder> props)
}

// Third by sorting Creator properties before other unordered properties
if (_creatorProperties != null) {
// (unless strict ordering is requested)
if (_creatorProperties != null && !_config.shouldPreservePropertiesOrdering()) {
/* As per [databind#311], this is bit delicate; but if alphabetic ordering
* is mandated, at least ensure creator properties are in alphabetic
* order. Related question of creator vs non-creator is punted for now,
Expand Down
34 changes: 30 additions & 4 deletions src/test/java/com/fasterxml/jackson/databind/ObjectMapperTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public void testCopy() throws Exception
assertTrue(m.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED));

// // First: verify that handling of features is decoupled:

ObjectMapper m2 = m.copy();
assertFalse(m2.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES));
m2.enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
Expand Down Expand Up @@ -215,7 +215,7 @@ public void testFailedCopy() throws Exception
}
}

public void testAnnotationIntrospectorCopyin()
public void testAnnotationIntrospectorCopying()
{
ObjectMapper m = new ObjectMapper();
m.setAnnotationIntrospector(new MyAnnotationIntrospector());
Expand Down Expand Up @@ -272,6 +272,32 @@ public void testConfigForPropertySorting() throws Exception
assertTrue(dc.shouldSortPropertiesAlphabetically());
}

// Test to ensure that we can check forced property ordering defaults...
public void testConfigForForcedPropertySorting() throws Exception
{
ObjectMapper m = new ObjectMapper();

// sort-alphabetically is disabled by default:
assertFalse(m.isEnabled(MapperFeature.STRICT_PROPERTIES_ORDERING));
SerializationConfig sc = m.getSerializationConfig();
assertFalse(sc.isEnabled(MapperFeature.STRICT_PROPERTIES_ORDERING));
assertFalse(sc.shouldPreservePropertiesOrdering());
DeserializationConfig dc = m.getDeserializationConfig();
assertFalse(dc.shouldPreservePropertiesOrdering());

// but when enabled, should be visible:
m = jsonMapperBuilder()
.enable(MapperFeature.STRICT_PROPERTIES_ORDERING)
.build();
sc = m.getSerializationConfig();
assertTrue(sc.isEnabled(MapperFeature.STRICT_PROPERTIES_ORDERING));
assertTrue(sc.shouldPreservePropertiesOrdering());
dc = m.getDeserializationConfig();
// and not just via SerializationConfig, but also via DeserializationConfig
assertTrue(dc.isEnabled(MapperFeature.STRICT_PROPERTIES_ORDERING));
assertTrue(dc.shouldPreservePropertiesOrdering());
}

public void testJsonFactoryLinkage()
{
// first, implicit factory, giving implicit linkage
Expand All @@ -284,7 +310,7 @@ public void testJsonFactoryLinkage()
assertSame(m, f.getCodec());
}

public void testProviderConfig() throws Exception
public void testProviderConfig() throws Exception
{
ObjectMapper m = new ObjectMapper();
final String JSON = "{ \"x\" : 3 }";
Expand Down Expand Up @@ -332,7 +358,7 @@ public void testCustomDefaultPrettyPrinter() throws Exception
assertEquals("[1,2]", m.writer().without(SerializationFeature.INDENT_OUTPUT)
.writeValueAsString(input));
}

// For [databind#703], [databind#978]
public void testNonSerializabilityOfObject()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,22 @@ public BeanForGH311(@JsonProperty("b") int b, @JsonProperty("a") int a) { //b an
public int getB() { return b; }
}

static class BeanForStrictOrdering {
private final int a;
private int b;
private final int c;

@JsonCreator
public BeanForStrictOrdering(@JsonProperty("c") int c, @JsonProperty("a") int a) { //b and a are out of order, although alphabetic = true
this.a = a;
this.c = c;
}

public int getA() { return a; }
public int getB() { return b; }
public int getC() { return c; }
}

// For [databind#2879]
@JsonPropertyOrder({ "a", "c" })
static class BeanFor2879 {
Expand Down Expand Up @@ -126,6 +142,11 @@ static class OrderingByIndexBean {
.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true)
.build();

private final ObjectMapper STRICT_ALPHA_MAPPER = jsonMapperBuilder()
.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY)
.enable(MapperFeature.STRICT_PROPERTIES_ORDERING)
.build();

public void testImplicitOrderByCreator() throws Exception {
assertEquals("{\"c\":1,\"a\":2,\"b\":0}",
MAPPER.writeValueAsString(new BeanWithCreator(1, 2)));
Expand Down Expand Up @@ -187,4 +208,10 @@ public void testOrderByIndexEtc() throws Exception
assertEquals(aposToQuotes("{'f':0,'u':0,'b':0,'a':0,'r':0}"),
ALPHA_MAPPER.writeValueAsString(new OrderingByIndexBean()));
}

public void testStrictAlphaAndCreatorOrdering() throws Exception
{
String json = STRICT_ALPHA_MAPPER.writeValueAsString(new BeanForStrictOrdering(1, 2));
assertEquals("{\"a\":2,\"b\":0,\"c\":1}", json);
}
}