-
Notifications
You must be signed in to change notification settings - Fork 3
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
feat: preserveKeyOrder option #32
Conversation
@@ -514,4 +514,126 @@ european-cities: &cities | |||
expect(result.diagnostics).toEqual([]); | |||
}); | |||
}); | |||
|
|||
describe('keys sorting', () => { | |||
it('does not retain the order of keys by default', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a performance thing? Should we retain order of keys by default?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we retain order of keys by default?
Not sure, probably not? I believe we want to stay close to JSON.parse
, don't we?
Either way, this data won't be preserved anyway when the structured copy is performed, so well, Studio won't benefit too much regardless.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does JSON parse not retain key order? If this does not make a meaningful difference on performance, I suggest we do this by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does JSON parse not retain key order?
It does not.
If this does not make a meaningful difference on performance, I suggest we do this by default.
The parsing performance is not affected too much. It's around 25-35% slower, which isn't terrible.
The "trapped" access is slower by quite some marging in certain circumstances. I made a few Object.keys
calls on a few properties from HugeYaml
fixture, and they took 15-25 times longer.
Object.getOwnPropertyNames
and Reflect.ownKeys
aren't particularly slower - only 2-4 times. I didn't test Object.getOwnPropertySymbols
, since it didn't make any sense.
That said, I guess we can make it disabled by default.
// reduceRight is on purpose here! We need to respect the order - the key cannot be overridden.. | ||
return items.reduceRight((merged, item) => Object.assign(merged, item), {}); | ||
// reduceRight is on purpose here! We need to respect the order - the key cannot be overridden | ||
const reduced = items.reduceRight( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have a sense of how this sortKeys option affects performance?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll check it.
Frankly speaking, though, I didn't expect to use it anywhere else than Spectral CLI, as in every other case the order does not really matter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well... I would expect this to be true - xyz === yaml.stringify(yaml.parse(xyz))
. Is this not the case right now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
xyz === yaml.stringify(yaml.parse(xyz))
This will be true, but Object.keys(yaml.parse(xyz))[0] === Object.keys(yaml.parse(yaml.stringify(yaml.parse(xyz))))[0]
won't if such a YAML document is provided
"foo": true
"0": false
Object.keys(xyz)[0] // equals "foo"
Object.keys(yaml.stringify(yaml.parse(xyz)))[0] // equals "0"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
xyz is a string right? So Object.keys(xyz)
doesn't apply.
If key ordering is not preserved, I don't understand how xyz === yaml.stringify(yaml.parse(xyz))
could be true?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah sorry, I meant to write Object.keys(yaml.parse(xyz))[0] // equals "foo"
😅
If key ordering is not preserved, I don't understand how xyz === yaml.stringify(yaml.parse(xyz)) could be true?
The key ordering should be preservered during stringification, but it won't be upon the second parsing unless preserveOrderKey
is passed again.
I screwed the example there. Here is a correct one.
Object.keys(yaml.parse(xyz, { preserveKeyOrder: true }))[0] === Object.keys(yaml.parse(yaml.stringify(yaml.parse(xyz, { preserveKeyOrder: true }))))[0] // false
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can also add a test if you'd like to
test('preserves the order of keys', () => {
const xyz = `foo: true
bar: false
"1": false
"0": true
`;
expect(safeStringify(parseWithPointers(xyz, { preserveKeyOrder: true }).data)).toEqual(
safeStringify(parseWithPointers(safeStringify(parseWithPointers(xyz, { preserveKeyOrder: true }).data), {
preserveKeyOrder: true,
}).data as any),
); // this assertion is met
expect(safeStringify(parseWithPointers(xyz, { preserveKeyOrder: true }).data)).toEqual(
safeStringify(parseWithPointers(safeStringify(parseWithPointers(xyz, { preserveKeyOrder: true }).data)).data as any),
); // this assertion is not met
});
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right but wouldn't one expect myString === JSON.stringify(JSON.parse(myString))
to be true?
Take Studio for example - if user opens YAML file, we parse it into memory and then stringify and write it back to disk. What it sounds like is that what is written back to disk will not equal what was originally on disk (key ordering not maintained).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Take Studio for example - if user opens YAML file, we parse it into memory and then stringify and write it back to disk. What it sounds like is that what is written back to disk will not equal what was originally on disk (key ordering not maintained).
It depends on the value of preserveKeyOrder
and the YAML document itself (if it has no numeric scalar mapping keys, everything will be okay).
🎉 This PR is included in version 3.4.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Needed for stoplightio/spectral#730