-
Notifications
You must be signed in to change notification settings - Fork 253
Make it possible to have a deterministic order in serialized OpenApi files #1314
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
Comments
FWIW (in case someone has the same issue and stumble on this feature request), I found a workaround, which is in a nutshell:
From a code point of view it looks like this:
That being said, I guess it makes sense to leave this feature request open, because it would be much more convenient if this could be supported directly by |
Related: dotnet/aspnetcore#59809 |
@RachitMalik12 Can we slot this in for v2? I don't think we necessarily have to change anything about the in-memory model to support sorting but the serialization step should attempt do lexogaphic sorting on the path values before seralizing the document. Similarily, we should probably lexographic sort the elements when in each component type? For example, all schemas get sorted alphabetically by ID and all security schemes as well. |
@captainsafia I think I would rather the default behaviour to be to maintain the order provided by the user, but we would be open to providing a Sort() method to reorder the dictionary. |
Relevant for all dictionary based collections |
My assumption here was that we'd provide either a comparer or a callback on the settings object so it can be used during the serialization. |
@baywet There are two distinct work items here.
|
To maintain the order we could replace all the Dictionaries we have by OrderedDictionary I thought it was only available for net5+ but it goes all the way back to netstandard2.0, which is good news for us. As for the helper, I'm assuming this is only relevant during serialization? there are no other scenarios which would require control over ordering from the user? correct? We have other places where we use lists, they maintain order. We also have hashsets, they don't have an OrderedSet equivalent. Would you leave it as is? or also require to use an ordering collection instead? |
@baywet OrderedDictionary sounds good. Yes I think the ordering is only necessary during serialization, but why does it matter if we just have a helper method? Are you thinking of doing this a different way, like in the writer settings? I looked at some places where we have HashSet and I think we may need to change this too. We use it for Tags and considering Tags are used for generating documentation, the order might end up being significant to doc rendering. Are there any downsides to changing from HashSet? Is it just that we lose the uniqueness constraint? |
@darrelmiller there's something I don't understand here. If we're talking about simply helper methods, and not updating the writer settings, how do you expect people to use them? reorder the DOM and THEN serialize? As for hashsets, we could simply "implement it" by creating a new HashSet class that effectively stores everything in an OrderedDictionary<T,bool> under the hood, and discard the value all the time. The main downside is the memory footprint and maybe the and increased compute time as well. |
yes. Most people will create the dom objects and then just serialize in the order they created. However, asp net are generating from code so they want to sort before serializing to minimize diffs if code gets reorganized |
So they effectively ONLY need a call back during serialization time. It's ok if deserialization-serialization is NOT symmetric in terms of order (assuming no callback is passed). Which means we don't need to change collections. Correct? |
I can confirm that we only need to order these dictionaries during serialization. How will this work for arrays, such as the global tags array? We will want to generate this in a deterministic order as well, probably sorted by tag name. |
@baywet ASPNET only need it sorted at serialization time. However, we have had requests from other users to have deterministic ordering. I think we should fix the collections so we never have non-deterministic ordering. Having the collections sorted alphabetically is a distinct issue that is the ASP.NET requirement. |
@mikekistler do you think you'd ever have a requirement to sort collections in a different way? (e.g. tags a specific way, but path items another) If we think this is not enough context to do the sorting, we could instead ONLY replace all collections by ones that maintain order, and let you do the sorting on the object model directly. Doing that would reduce the API surface, also fix the symmetry problem, and give you greater control. Thoughts? |
I don't foresee a need for custom sorting options, but if possible I would like to allow a developer to override the sorted collection with an ordered collection. In other words, I think the two options of a) sorted lexicographically by the natural key, and b) a custom ordered dictionary should cover all the bases. |
Let's see:
That's more than I expected, and I might have missed some. |
Please don't reorder these. They represent something functional that users care about. For example: public class Employee
{
public long Id { get; set; }
public string DisplayName { get; set; }
public decimal Salary { get; set; }
} should be emitted as:
instead of:
Users expect to find The remainder of the OAS file is technical, as it does not represent the business entities from an app, so the ordering should not matter much. |
This isn't about reorder properties on schemas. It's about ordering in the for top-level items under the |
Is your feature request related to a problem? Please describe.
I use OpenAPI.NET to serialize instances of
OpenApiDocument
and store them in a git repo.So, ideally I would like that when I make a simple change to my API, I get a simple change in the serialized document, in order to have an easy to review git diff.
It is not the case currently, because serialization iterates on some
Dictionary
and that the order of the iteration is hence not deterministic.For instance, if I add one endpoint to my API, I would like that my serialized OAS file looks like what it was at my previous generation, with just a few added lines. But in practice I may have more diffs, because my paths and my schemas may end up serialized in a different order.
Describe the solution you'd like
I can already achieve part of what I would like from my client code in the sense that I can get a deterministic order for the Schemas section, if I do
It works rather fine, in the sense that it leads to a serialized
schemas
section where all schemas are order alphabetically (making it nice for my git diffs, and making the file easier to browse overall). However, it does not feel really "clean" in itself, and this approach does not work for other parts of the document. In particular for the paths; because they are represented by anOpenApiPaths
which ends up extending aDictionary
and I could not find a virtual method or an attribute I could override to achieve a similar deterministic order.Given this context, a solution that would be nice would be to edit
IOpenApiSerializable
in order to turnSerializeAsV3(IOpenApiWriter writer)
intoSerializeAsV3(IOpenApiWriter writer, bool enforceAlphabeticalOrder = false)
.So for instance
OpenApiExtensibleDictionary.SerializeAsV3
could be implemented likeHaving this feature behind a boolean
enforceAlphabeticalOrder
could make it possible for users interested in this feature to use it, and users not interested in it would not suffer any performance penalty by leaving it to false.Describe alternatives you've considered
As explained above, I tried to achieve this order from my client code, but faced some hard limitations
Additional context
If the proposed approach looks good to you, and if it could help, I guess I could try to propose a pull request to implement this.
The text was updated successfully, but these errors were encountered: