web-dev-qa-db-ja.com

Swift Codableを使用してJSONにシリアル化するときに文字列がエスケープされる

次のようにオブジェクトをシリアル化しようとしています:

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)
}

しかし、macOSでは次のものが得られます:

{"profileURL":"http:\/\/google.com","username":"John"}

(エスケープされた「/」文字に注意してください)。

Linuxマシンでは次のようになります:

{"username":"John","profileURL":"http://google.com"}

JSONEncoderにエスケープされていないものを返すにはどうすればよいですか?

JSONの文字列を厳密にエスケープ解除する必要があります。

24
tofiffe

私はreplacingOccurrences(of:with:)を使用することになりました。これは最良の解決策ではないかもしれませんが、問題は解決します。

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)
}
10
tofiffe

わかった。問題は、\文字が含まれていないことでした。 Swiftのプロパティにすぎません。コンソールで常にそのような文字列を返します。回避策は、j-sonで解析することです。

それでも、「\ /」を「/」文字列に置き換える解決策の下で使用できます

 let newString = str.replacingOccurrences(of: "\\/", with: "/") 
 print(newString)
4
Ashish

iOS 13+/macOS 10.15 +

使用できます .withoutEscapingSlashes スラッシュのエスケープを回避するJSONデコーダーのオプション

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)
}

コンソールO/P

{"profileURL": " http://google.com "、 "username": "John"}


注:Martin R のコメント\/は有効なJSONエスケープシーケンスです。

3

JSONEncoder/JSONDecoderで遊んでいると、エンコード->デコードでURLタイプが非可逆であることがわかりました。

別のURLに関連する文字列で初期化します。

init?(string: String, relativeTo: URL?)

これが役立つかもしれませんApple document: https://developer.Apple.com/documentation/foundation/url

ただし、PropertyListバージョンを使用する場合:

let url = URL(string: "../", relativeTo: URL(string: "http://google.com"))! 
let url2 = PropertyListDecoder().decode([URL].self, from: PropertyListEncoder().encode([User]))

他の方法

let url = URL(string: "../", relativeTo: URL(string: "http://google.com"))! 
let url2 = JSONDecoder().decode([URL].self, from: JSONEncoder().encode([User]))

あなたに役立つことを願っています!!

1
BuLB JoBs