Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keep original order of JSON properties #92

Closed
udowal opened this issue Apr 29, 2020 · 14 comments · Fixed by #98 or #99
Closed

Keep original order of JSON properties #92

udowal opened this issue Apr 29, 2020 · 14 comments · Fixed by #98 or #99

Comments

@udowal
Copy link

udowal commented Apr 29, 2020

Hi,

in my project I need to keep the original order of JSON properties.
In "SchemaGenerationContextImpl.generateObjectDefinition (ResolvedType, ObjectNode)" the 2 lines

final Map<String, JsonNode> targetFields = new TreeMap<>();
final Map<String, JsonNode> targetMethods = new TreeMap<>();

could be replaced by something like this:

final Map<String, JsonNode> targetFields;
final Map<String, JsonNode> targetMethods;
if (this.generatorConfig.shouldKeepOriginalPropertiesOrder()) {
    targetFields = new LinkedHashMap<>();
    targetMethods = new LinkedHashMap<>();
} else {
    targetFields = new TreeMap<>();
    targetMethods = new TreeMap<>();
}

with the new method shouldKeepOriginalPropertiesOrder() and a new appropriate option.

Is it possible?

Best regards
Udo

@CarstenWickner
Copy link
Member

Hi Udo,

The look-up of fields (and methods) is done via the com.fasterxml:classmate library. For your proposal to work we'd have to assume that classmate is returning the properties in their declaration order.

If that assumption holds true, then your solution is pretty much all there is to it and it's thereby certainly possible.
Have you tested it already in a fork to confirm that it works as you expect it to?

@udowal
Copy link
Author

udowal commented Apr 29, 2020

Hi Carsten,

thank you for the fast answer.
I tested it locally without the if-else-statement:

final Map<String, JsonNode> targetFields = new LinkedHashMap<>();
final Map<String, JsonNode> targetMethods = new LinkedHashMap<>();

... and it works fine as expected, unit tests are green :).

@CarstenWickner
Copy link
Member

CarstenWickner commented Apr 29, 2020

Hi Udo,

I‘m not concerned about the existing unit tests, since they don’t check for the order of anything. Or are you talking about your own unit tests?

I was more interested in whether the properties are actually in the declaration order then and not some random or still alphabetic order.

@udowal
Copy link
Author

udowal commented Apr 29, 2020

Hi Carsten,

yes, they are in the declaration order (no own unit tests).

@CarstenWickner
Copy link
Member

Hi Udo,

I tried it now myself but can unfortunately not confirm your observation that the declaration order is being preserved.
Looks to me like classmate is not respecting the declaration order – resulting in an unreliable order of the properties being returned – which is the reason why I sorted them alphabetically in the past, to make it at least predictable.

I'm open to alternative suggestions. 😉

@udowal
Copy link
Author

udowal commented Apr 30, 2020

Hi Carsten,

mh, in my case there are only member variables and therefore it works in my little world.
I didn't consider the case with constants, methods and a super class.

I'll have a look if there is a way to solve it (it will last a few days).

Thank you so long!

@udowal
Copy link
Author

udowal commented May 4, 2020

Hi Carsten,

I extended java SchemaGeneratorOptionsTest and added constants and methods to java TestClass1 and java TestClass2. But except for the member variables there is apparently no rule in ordering the constants and methods.
Also I dived into java classmate but without any idea.

So I will call java generator.generateSchema(My.class) and re-order the result in my code.

I'm sorry to guide you on the wrong track.

@udowal udowal closed this as completed May 4, 2020
@CarstenWickner
Copy link
Member

CarstenWickner commented May 4, 2020

Hi @udowal,

nothing to be sorry about. It's a valid concern. I guess especially so if the generated schema is supposed to be used in contexts like the automatic generation of UI forms.

I also investigated a bit and it seems like classmate is preserving the order of properties from the bytecode. However, it depends on the compiler that was used to generate the bytecode whether the original declaration order in the source code was preserved. According to the Java specification, that order does not seem to be guaranteed. I.e. one would have to access the source code somehow or convey the desired order in another way, e.g. annotations on the code like the Jackson @JsonPropertyOrder.

Maybe the generator could offer some way of configuring the desired sorting method – by default: the current alphabetic sorting of the property names – where one could either not sort at all and hope the compiler preserved the declaration order and/or sort by these kinds of annotations (or some other means).

Let's maybe keep this issue here open until this has been addressed.

@CarstenWickner CarstenWickner reopened this May 4, 2020
@udowal
Copy link
Author

udowal commented May 7, 2020

Hi Carsten,

yes, in my project UI forms are generated automatically.

I'm looking forward to the extension.

Best regards
Udo

@CarstenWickner CarstenWickner linked a pull request May 9, 2020 that will close this issue
@CarstenWickner CarstenWickner linked a pull request May 10, 2020 that will close this issue
@CarstenWickner
Copy link
Member

The ability to sort an object's properties has been added to the jsonschema-generator (GH-98).
Additionally, the jsonschema-module-jackson now allows for the @JsonPropertyOrder annotation to be respected – triggered via a new JacksonOption.RESPECT_JSONPROPERTY_ORDER (GH-99).

This will be included in the next release v4.12.0 then.

@CarstenWickner
Copy link
Member

CarstenWickner commented May 10, 2020

Release v4.12.0 has been published now.

If you trust your compiler, you can simply configure the new property sorting configuration to always return zero (0) and thereby preserve the order as per the Java Byte Code. 😉

@udowal
Copy link
Author

udowal commented May 11, 2020

Hi Carsten,

simple and fast.
Great - thank you!

Best regards
Udo

@neumannm
Copy link

Hi @CarstenWickner - is the configuration for sorting an object's properties also available in the Maven plugin, and if so, how is this expressed in the plugin's configuration? Thanks.

@CarstenWickner
Copy link
Member

Hi @neumannm,

You'd have to wrap your desired configuration into an implementation of the Module interface, make it available on the Maven plugin's classpath and then reference it like the "standard" plugins.
That way, you can make use of all advanced configurations – such as sorting an object's properties in a particular way.

Unless you're using the JacksonModule and want the @JsonPropertyOrder annotation to be respected. For that, you'd only have to include the existing RESPECT_JSONPROPERTY_ORDER option in the Maven plugin configuration, as mentioned here: https://victools.github.io/jsonschema-generator/#further-configurations-through-modules

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
3 participants