Hello,
I'd like to ask a very fundamental question about JSONEncoder
: how to sort keys in a specific order when encoding a dictionary to JSON text?
I know there is an option called JSONEncoder.OutputFormatting.sortedKeys
, but it sorts the keys only in lexicographic order.
I want to sort the keys using a different comparator, such as String.localizedStandardCompare(_:)
, which achieves the "Finder-like" order.
The reason why I ask this question is because I have a localization tool that works with String Catalog (xcstrings file, which is a JSON), but every time my tool serializes an xcstrings file, it always messes up the keys in lexicographic order (I used JSONEncoder
+ .sortedKeys
). Meanwhile, Xcode 16 always serializes the string keys into the "Finder-like" order. As a result, my tool always generates a huge diff when manipulating the xcstrings even when making only a small modification to it.
So I am wondering how Xcode 16 implements the String Catalog tool to serialize the JSON in "Finder-like" order. It would be great if JSONEncoder
could do that too. Or, maybe I can use another serialization method to implement this behavior?
how to sort keys in a specific order when encoding a dictionary to JSON text?
You can’t. The JSON standard is very clear that dictionaries are not ordered. The ability of JSONEncoder
to sort the keys is an affordance for folks who want to maintain key stability, for creating nice diffs and so on. However, it has no way to override that sort order (r. 132654941).
Only Xcode 16 serializes the String Catalog files into the "Finder-like" order. In Xcode 15, the String Catalog files are in lexicographic order. So, this is a new in Xcode 16.
I think you should file a bug about that. I can see why Xcode might have made this change, but it’s messing up your tool and I can imagine it messing up other tools as well. Please post your bug number, just for the record.
As to what you can do about it right now, there isn’t a way to override this with JSONEncoder
. Your only real option is to write or acquire your own library for JSON rendering.
I also think it’d be reasonable to file an enhancement request against JSONEncoder
for more control over the sort order. I’m not sure that’ll get any traction — there’s a strong impetus to maintain the unsorted nature of dictionaries — but you have a pretty reasonable use case.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"