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

Feature: Convert while preserving the order of fields in objects #903

Open
eteichm opened this issue Mar 31, 2021 · 13 comments
Open

Feature: Convert while preserving the order of fields in objects #903

eteichm opened this issue Mar 31, 2021 · 13 comments

Comments

@eteichm
Copy link

eteichm commented Mar 31, 2021

I suggest to add the feature of preserving the order of list items when converting to json, maybe as an option. If available, please add it to the manual.

@sbarzowski
Copy link
Collaborator

Order of list elements is always preserved. Do you mean the order of object fields?

@eteichm
Copy link
Author

eteichm commented Apr 1, 2021

Yes, I meant preserving the order of object fields. Currently, they seem to be sorted in alphabetical order.

@sbarzowski sbarzowski changed the title Feature: Convert while preserving the order of list items Feature: Convert while preserving the order of fields in objects Apr 1, 2021
@sbarzowski
Copy link
Collaborator

There are some existing issues about that (#407, probably something on go-jsonnet side as well...). There are some good reasons not to do it (it shouldn't matter, JSON objects are unordered), but it could be a usability win. So, if someone can propose a good, coherent solution I'll be happy to help make it happen.

It's not exactly clear how to handle this in all cases. There were some discussions in the mailing list about that as well.

Closing this for now and re-opening the original issue (where we have more context).

@1pakch
Copy link

1pakch commented Apr 1, 2021

My 2c is that not sorting the keys would also interfere with content hashing use-case e.g. doing std.md5(std.toString(obj)).

@sbarzowski
Copy link
Collaborator

@ilya-kolpakov Yes, that is correct. We certainly want to keep backwards compatibility w.r.t. how objects are manifested. So probably some additional hidden parameter on an object would be necessary to have fields manifested in non-alphabetical order.

@arpitjasa-db
Copy link

Hi @sbarzowski is there any update on this?

@sbarzowski
Copy link
Collaborator

@arpitjasa-db Not really. You can take a look at the mailing list for the related discussion.

If someone can come up with an acceptable proposal and wants to implement it, I'll be happy to support it.

@CertainLach
Copy link
Contributor

I have experimented with this feature in my Rust implementation of Jsonnet, what do you folks think about this?
https://github.com/CertainLach/jrsonnet/releases/tag/v0.5.0-pre1-test

@sbarzowski
Copy link
Collaborator

Nice! Some questions:

  • This is deep, right? I.e. preserve_order applies to nested object as well, right?
  • What exactly happens to the order of elements with +? Do you always put the overridden fields after the untouched ones?
  • How does it work with object comprehensions?

If we can agree on semantics I'm happy to upstream this (unless @sparkprime protests).

@CertainLach
Copy link
Contributor

Yep, serialization order is applied deeply
I can't think of any case, where mixed ordering would be useful

I always put overriden fields after untouched, however i think + should keep old ordering of original field, i will change that

In object comprehensions fields are ordered by insertion, i.e {[k]: 1 for k in ['b', 'a', 'c']} will have b, a, c ordering

@sbarzowski
Copy link
Collaborator

I always put overriden fields after untouched, however i think + should keep old ordering of original field, i will change that

Yeah. I expect the most common case would be to have a big object with fields in expected order and then override some of them. It would be annoying if this would always put them in the end.

In object comprehensions fields are ordered by insertion, i.e {[k]: 1 for k in ['b', 'a', 'c']} will have b, a, c ordering

Sounds reasonable.

@CertainLach
Copy link
Contributor

CertainLach commented Apr 30, 2022

I have played with this feature couple of days, and i think about this as better behavior:

Both overrides and + should keep position of original field declaration:

{a: 1, b: 2} + {c: 4, a: 2, b+: 1}
// =>
{a: 2, b: 3, c: 4}

Originally i was resetting position of overriden field to have better understanding for where this field was defined, but this breaks cases like

{apiVersion: error "missing api version", kind: error "missing kind"} + {kind: 'Pod', apiVersion: 'v1'}

For my usecase i should better think about something like manifestDebug, which will yield something like

{apiVersion: <overriden>, kind: <overriden>} + {kind: 'Pod', apiVersion: 'v1'}

CertainLach added a commit to CertainLach/jrsonnet that referenced this issue May 1, 2022
Per discussion in google/jsonnet#903

Signed-off-by: Yaroslav Bolyukin <iam@lach.pw>
@sbarzowski
Copy link
Collaborator

Agreed. I like your approach and would be happy to make it official.

manifestDebug

This technically breaks some laws that + on object is supposed to follow (e.g. exposes internal structure of the object to the user, so you can no longer override everything completely). I understand this is intended just as a debugging feature, but it's not something I would like to have upstream :-).

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

No branches or pull requests

5 participants