Nevin
1
I want to customize the output of a JSONEncoder.
The prettyPrinted formatting option does what I want for containers with multiple values. That is, arrays with at least 2 elements, dictionaries with at least 2 keys, objects with at least 2 fields, and so forth.
But when an array, dictionary, or object has only one entry (or none), I want the encoded json to stay on a single line (provided the entry itself encodes to a single-line result).
For example:
// [Int]
[] // Encode to []
[1] // Encode to [1]
[1, 2] // Encode to:
// [
// 1,
// 2
// ]
// [String: [Int]]
["a": []] // Encode to { "a" : [] }
["a": [1]] // Encode to { "a" : [1] }
["a": [1], "b": [2]] // Encode to:
// {
// "a" : [1],
// "b" : [2]
// }
["a": [1, 2]] // Encode to:
// {
// "a" : [
// 1,
// 2
// ]
// }
Is something like this possible?
What about taking it further by letting multi-element arrays encode to a single line (with a space after each comma), unless that would result in a length exceeding some threshold?
Basically, I’m looking for a “compactPrettyPrinted” format, which uses whitespace and newlines freely, but not excessively. Does such a thing exist, or is there a way to create one?
As you could see by checking the documentation, both answers are clearly no.
If I remember well, JSONEncoder is based on NSJSONSerialization, whose options are NSJSONWritingOptions | Apple Developer Documentation.
You may ask for an update to Foundation, or look for another JSON serialization utility, maybe.
1 Like
itaiferber
(Itai Ferber)
3
Indeed, JSONEncoder is currently backed by JSONSerialization, which doesn't offer this level of customizability (or a hook to provide it yourself). I also recommend filing some feedback with Apple, but in the meantime, it might be best to investigate a 3rd-party JSON-formatting library to pass the data through.
1 Like
Jens
4
Or you could "just" reformat the pretty printed output yourself, via eg an extension on String:
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let output = try! encoder.encode(value)
let jsonStr = String(data: output, encoding: .utf8)!
.compactingPrettyPrintedJSON(maxLineLength: 80) // <-- implement something like this
Though it would certainly be nicer if JSONEncoder was more customizable.
2 Likes