If you JSON-decode material containing a value that contains a backslashed "n" to indicate a newline, at what point should you replace it with a true newline?
Here's an artificial example:
let dict = ["key": "value\\nvalue"]
let json = try! JSONEncoder().encode(dict)
let result = try! JSONDecoder().decode([String:String].self, from: json)
print(result["key"])
That outputs "value\\nvalue", but for purposes of display in my app, I then call replacingOccurrences to change "\\n" (meaning backslashed n" into "\n" (meaning newline) so that an actual newline appears in my interface.
Now, I'm a little surprised that JSONDecoder isn't already doing this for me. Just as it has a configurable policy for decoding a date string value into a date, I would expect it at the least to have a configurable policy for decoding a string value into a string. But it doesn't.
My question is: what do people do about this sort of situation, as a general rule? Dealing with it on a case by case basis, as I'm doing in my app, feels wrong; in reality, these JSON data are coming from the server and I want all JSON HTTP response bodies to be treated in this way.
It looks like the server is sending 5c5c6e (i.e. backslash-backslash-n or
\\n). That's valid JSON, but it doesn't mean "newline." It means "backslash-n" (\followed byn). If the server means to send newline, that's mis-encoded. It needs to be 5c6e, "backslash-n." Sure, you can fix it on the client side, but there's no "normal" way to do that because it's just wrong.The right way to fix that is to fix it on the server side. You can double-unescape the strings on the client-side, but that's ambiguous and I don't recommend it unless there's no better way. Repeatedly unescaping tends to mess things up when actual backslashes show up in the string.
"Literal newlines" are not allowed in JSON strings in that the byte 0a is not allowed between quotation marks. Putting that into JSONLint should fail. But 5c6e (backslash-n or
\n) is, and is the correct way to do it.