eclipse-ee4j / yasson

Eclipse Yasson project
https://projects.eclipse.org/projects/ee4j.yasson
Other
204 stars 96 forks source link

Using LinkedHashMap to preserve attribute order #266

Open fhm84 opened 5 years ago

fhm84 commented 5 years ago

When using a generic approach in our Java model (-> maps), we'd like to preserve the attribute order "as is". So it would be great to configure whether to not order attributes or preserve the given order (perhaps only when using collections/maps). What do you think about using LikedHashMap as default implementation when PropertyOrderStrategy is set to ANY?

aguibert commented 5 years ago

hi @fhm84 thanks for raising this issue. When you say "preserve attribute order" I assume you mean preserving the order that fields/methods were defined in the source file?

If that is what you mean, it's not currently possible to guarantee such an ordering, because the JDK does not provide an API to obtain fields/methods in a way that matches the source ordering.

What do you think about using LikedHashMap as default implementation when PropertyOrderStrategy is set to ANY?

I don't think this would be right, because typically when users specify ANY ordering they don't care about ordering at all, and usually we see this option specified when people want to maximize performance. Currently we use HashMap which is very efficient for put/get operations, and switching this to LinkedHashMap would be much slower.

However, we could consider making a new PropertyOrderStrategy (perhaps called SOURCE) which would make a best effort to order properties in the source ordering, but ultimately would depend on the behavior of the JDK reflection APIs which do not guarantee ordering.

fhm84 commented 5 years ago

Hi @aguibert thanks for the response. When I say "preserve attribute order" I mean when e.g. reading a json file and mapping it to its corresponding java model the file should look the same if I write this data back to a file again. Currently we use json files for configuring our system where sometimes the ordering of some properties matters. But here we cannot implement a custom naming strategy for ordering, except of introducing additional fields only for this purpose, because the data model is a generic one. In the past we used Jackson as json mapper and in the beginning they had the same issues. But we decided to use "the standard" apis.

I know that looking on performance a HashMap is much more efficient. So your idea to add a new PropertyOrderStrategy sounds very good. As you can see my issue is not to preserve attribute order of the source file(s) (I know the jdk does not guarantee the attribute/method ordering) but preserve the order when reading from a file.

aguibert commented 5 years ago

Currently we use json files for configuring our system where sometimes the ordering of some properties matters.

If property order matters, then perhaps your data model should reflect this? For example, an array could be used instead of a set which does preserver ordering.

As you can see my issue is not to preserve attribute order of the source file(s) (I know the jdk does not guarantee the attribute/method ordering) but preserve the order when reading from a file.

So essentially if you go JSON --> POJO --> JSON you want the input JSON to be equal to the resulting JSON? This should be the case already because the default PropertyOrderStrategy defined by the spec is A-Z ordering. Is this not what you are observing?

nimo23 commented 4 years ago

Currently we use HashMap which is very efficient for put/get operations, and switching this to LinkedHashMap would be much slower.

  1. Does this mean that PropertyOrderStrategy.ANY, the ordering for each (de)serializing of the same object is arbitrarily?

PropertyOrderStrategy.SOURCE cannot be made without reflection

  1. Maybe yes, with the Java MethodHandles API such reflection is not needed, or?

  2. Btw, does Yasson also need reflection api if I use something like this?:

@JsonbNillable(value = true)
@JsonbVisibility(value = PrivatePropsVisible.class)
// reflection api needed?
@JsonbPropertyOrder(value = {
"firstProp",
"secondProp",
"thirdProp"
})
public class Task {
    private int firstProp;
    private int secondProp;
    private int thirdProp;
}

Maybe Yasson can use Java MethodHandles API instead of Java Reflection to avoid performance drawbacks.

OrangeDog commented 4 years ago

So essentially if you go JSON --> POJO --> JSON you want the input JSON to be equal to the resulting JSON? This should be the case already because the default PropertyOrderStrategy defined by the spec is A-Z ordering. Is this not what you are observing?

That's not what this is asking for, and is also not correct. The input will only equal the output if the input was in alphabetical order.

What this issue is asking for is when doing JSON -> Map<String, Object> -> JSON, that there should be an option for a LinkedHashMap to be used, and the ordering preserved.