jackson-databind icon indicating copy to clipboard operation
jackson-databind copied to clipboard

`@JsonPropertyOrder(alphabetic = true)` does not include `@JsonAnyGetter`

Open lathspell opened this issue 10 years ago • 10 comments

The JsonPropertyOrder annotation does only sort the explicitly defined properties of an object, additional properties which may be stored using the JsonAnySetter/JsonAnyGetter annotations are not taken into account and just appended at the end.

This is not a bug as the order of properties in a JSON object should never be of any importance but when dumping objects into logs or diffing JSON outputs in unit tests it would be nice if the ordering would be alphabetic for all properties.

(if a TreeMap is used for the additionalProperties at least they for themselves are orderd alphabetic too)

lathspell avatar Aug 07 '14 16:08 lathspell

Hmmmh. True, sorting does not apply there, nor is it easy to implement the way sorting is implemented, as it applies to property accessor objects (name of which are known statically), and "any getter" applies to fully dynamic names. Regardless, I can see why it would be good for sorting to apply to any-getters as well. Just need to think of a good way to do that.

cowtowncoder avatar Aug 08 '14 02:08 cowtowncoder

+1 for this. Would also be happy to have the default behavior for anygetter either be alphabetical or have an option for that.

hdave avatar Sep 29 '14 14:09 hdave

Adding sorting just for any getter (without merging with 'non-any' properties) could be simpler first step. Although not sure if it'd be valuable without the other part.

cowtowncoder avatar Sep 29 '14 15:09 cowtowncoder

+1 for this.

heroicefforts avatar Jan 28 '16 20:01 heroicefforts

+1 for this also, however would like to be able to specify the property order explicitly (rather than alphabetic). Would really like to specify the location of the @JsonAnyGetter property and have all of it's fields all serialised in that location. eg.

@JsonPropertyOrder({ "propFirst", "propJsonAnyGetter", "propLast" })

brendanborgelt avatar Feb 21 '18 09:02 brendanborgelt

Dumb work-around if it fits your needs: You can use a TreeMap - the default comparator sorts keys lexicographically. You can use a custom comparator to sort keys differently.

jcalcote avatar Jul 18 '18 21:07 jcalcote

Case 1 : Allow @JsonAnyGetter-annotated property be respected by `@JsonPropertyOrder

(not the any, key-value properties added runtime via let's say map.put(k,v))

+1 for this also, however would like to be able to specify the property order explicitly (rather than alphabetic). Would really like to specify the location of the @JsonAnyGetter property and have all of it's fields all serialised in that location. eg.

It's been a while, but for tracking purposes, will share here. There is a PR #4396 under going, that covers (if completed) above requirements.

F.ex,

@JsonPropertyOrder({ "propFirst", "propJsonAnyGetter", "propLast" })
class Pojo {
...

... serialize any-getter property annotated with @JsonAnyGetter as defined via @JsonPropertyOrder

JooHyukKim avatar Mar 04 '24 03:03 JooHyukKim

Case 2 : any-properties added during runtime via @JsonAnyGetter to be order together with @JsonProperty

I guess, this case is what issue #518 meant for or might need separate merging of ordering between regular props and any-props due to performance reasons...?

    @JsonPropertyOrder({"a", "b", "c", "d"}) // Either this...
    @JsonPropertyOrder(alphabetic = true) // Or this
    static class AnyGetterOrdering {
        public int b = 2, d = 4;
        @JsonAnyGetter
        public Map<String,Integer> anyProps = new LinkedHashMap<>();
    }
    
    @Test
    public void testAnyGetterOrdering() throws Exception
    {
        // Given
        AnyGetterOrdering input = new AnyGetterOrdering();
        input.anyProps.put("a", 1);
        input.anyProps.put("c", 3);
        // When
        String json = MAPPER.writeValueAsString(input);
        // Then
        assertEquals(a2q("{'a':1,'b':2,'c':3,'d':4}"), json);
    }

JooHyukKim avatar Mar 04 '24 03:03 JooHyukKim

Just to make it clear: at first, I only propose that any-properties are sorted "as a block" and do not mix otherwise with regular properties. I also think that any-properties as a set/block are to be serialized using order they are iterated in from containing Map (etc). This also means that for sorting purposes, there is single virtual "name" for the set/block of any-properties, as if there was one logical Any Property container that participates in sorting.

I hope above makes sense wrt what I think should be done? (aside from question of whether that is what should be done :) ).

cowtowncoder avatar Mar 04 '24 16:03 cowtowncoder

Just to make it clear: at first, I only propose that any-properties are sorted "as a block"

This would be covered by Case 1, and...

and do not mix otherwise with regular properties.

... by Case 2. By NOT implementing Case 2, proposal would be satisfied I guess.

JooHyukKim avatar Mar 05 '24 00:03 JooHyukKim