FasterXML / jackson-databind

General data-binding package for Jackson (2.x): works on streaming API (core) implementation(s)
Apache License 2.0
3.52k stars 1.38k forks source link

SORT_PROPERTIES_ALPHABETICALLY doesn't work for partial constructors #2604

Open l0rinc opened 4 years ago

l0rinc commented 4 years ago

Given the following class:

class Child2 {
    public Object a1, b, a2;
    @JsonCreator public Child2(/*Object a1,*/ Object b /*, Object a2*/) {}
}

The following Spock test fails:

def "fields are sorted"() {
    def objectMapper = new ObjectMapper()
        .registerModule(new ParameterNamesModule())
        .enable(SerializationFeature.CLOSE_CLOSEABLE)
        .enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY)

    def jsonBuffer = new ByteArrayOutputStream()
    objectMapper.writeValue(jsonBuffer, new Child2(null))
    def serialized = jsonBuffer.toString()

    expect:
    serialized == '{"a1":null,"a2":null,"b":null}'
}

fails, since it's serialized to the keys b,a1,a2 (uncommenting the first param, i.e. @JsonCreator public Child2(Object a1, Object b /*, Object a2*/) {} would return a1, b,a2).

While this may be a relatively stable solution (not even sure about that, since apparently constructor changes can affect the order), it's definitely not alphabetic.

cowtowncoder commented 4 years ago

One quick note: sort order is a combination of multiple things, with different precedence. Highest precedence is for explicit order information (@JsonPropertyOrder( .... ), @JsonProperty(index = ...)); followed by "alphabetic" and "creator-bound properties first" general ordering info. I think ordering of creator-bound properties has higher precedence than more general alphabetic: but this should be documented better. And for 3.0 it might be reasonable to reconsider logic, as well; the only reason for trying to sort creator properties first is that this is typically good for deserialization (reduces need for buffering).

I'll tag this as 3.x although if I have time I'd like to verify current processing to make sure I understand how it works first, before considering possible changes.