Swift String escaping when serializing to JSON using Codable
Solution 1
For iOS 13+ / macOS 10.15+
You can use .withoutEscapingSlashes
option to json decoder to avoid escaping slashes
let user = User(username: "John", profileURL: "http://google.com")
let jsonEncoder = JSONEncoder()
jsonEncoder.outputFormatting = .withoutEscapingSlashes
let json = try? jsonEncoder.encode(user)
if let data = json, let str = String(data: data, encoding: .utf8) {
print(str)
}
Console O/P
{"profileURL":"http://google.com","username":"John"}
NOTE: As mention by Martin R in comments \/
is a valid JSON escape sequence.
Solution 2
I ended up using replacingOccurrences(of:with:)
, which may not be the best solution, but it resolves the issue:
import Foundation
struct User: Codable {
let username: String
let profileURL: String
}
let user = User(username: "John", profileURL: "http://google.com")
let json = try? JSONEncoder().encode(user)
if let data = json, let str = String(data: data, encoding: .utf8)?.replacingOccurrences(of: "\\/", with: "/") {
print(str)
dump(str)
}
Solution 3
I got it. The thing was that it didn't contain any \ character. It is just the property of swift that it will always return such a string on a console. The workaround is to j-son parse it.
Still, you can be used below solution of replacing '\/' with "/" string
let newString = str.replacingOccurrences(of: "\\/", with: "/")
print(newString)
Solution 4
While playing around JSONEncoder/JSONDecoder,
I found that the URL
type is lossy on encode -> decode.
Initializes with a string, relative to another URL.
init?(string: String, relativeTo: URL?)
Might be help this apple document: https://developer.apple.com/documentation/foundation/url
using the PropertyList
version, however:
let url = URL(string: "../", relativeTo: URL(string: "http://google.com"))!
let url2 = PropertyListDecoder().decode([URL].self, from: PropertyListEncoder().encode([User]))
Other way
let url = URL(string: "../", relativeTo: URL(string: "http://google.com"))!
let url2 = JSONDecoder().decode([URL].self, from: JSONEncoder().encode([User]))
Hope will helpful to you!!
user_4685247
Updated on June 17, 2022Comments
-
user_4685247 about 2 years
I'm trying to serialize my object as following:
import Foundation struct User: Codable { let username: String let profileURL: String } let user = User(username: "John", profileURL: "http://google.com") let json = try? JSONEncoder().encode(user) if let data = json, let str = String(data: data, encoding: .utf8) { print(str) }
However on macOS I'm getting the following:
{"profileURL":"http:\/\/google.com","username":"John"}
(note escaped '/' character).
While on Linux machines I'm getting:
{"username":"John","profileURL":"http://google.com"}
How can I make JSONEncoder return the unescaped?
I need the string in JSON to be strictly unescaped.
-
user_4685247 over 6 yearsAs it has been mentioned, the json is signed, adding percent encoding changes the signature and hash
-
Максуд Даудов over 6 years@tofiffe you cannot send url as parameter as it is. Either add removingpercent on server side( which you cannot) or send profileUrl with escaping symbols. Even on Linux, if you create such a string, there is no guarantee you can send to server as it is. If you send it to server with escaping symbols, it will change hash of profile url, right? So what, every time send percented string to validate it or something.
-
user_4685247 over 6 yearsAs I have shown in the question, it does not always return an escaped string (it works fine on Linux machines). When the JSON is parsed the problem is gone, but I need the JSON to be same as on the server
-
skagedal over 5 yearsThank you for giving an answer (although it's not super-satisfying) and I'm sorry you had too deal with all these people not answering your question and instead wanting you to ask a different question.
-
rustyMagnet over 5 yearsThanks. This still works. Shame there isn't a more elegant solution. the JSONEncoder APIs must be changing to allow this? People will shout "the JSON standard allows escaping". But I have deadline and a server that does not like the escape character.
-
Vyachaslav Gerchicov over 4 yearsare there ways to achieve the same result with iOS 12?
-
Inder Kumar Rathore over 4 yearsThe others answer may help you.