简体   繁体   English

使用Codable序列化为JSON时Swift String转义

[英]Swift String escaping when serializing to JSON using Codable

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: 但是在macOS上我得到以下内容:

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

(note escaped '/' character). (注意转义'/'字符)。

While on Linux machines I'm getting: 在Linux机器上,我得到:

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

How can I make JSONEncoder return the unescaped? 如何让JSONEncoder返回未转义的?

I need the string in JSON to be strictly unescaped. 我需要JSON中的字符串严格未转义。

I ended up using replacingOccurrences(of:with:) , which may not be the best solution, but it resolves the issue: 我最终使用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)
}

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. 它只是swift的属性,它总是会在控制台上返回这样一个字符串。 The workaround is to j-son parse it. 解决方法是j-son解析它。

Still, you can be used below solution of replacing '\\/' with "/" string 不过,您可以在下面使用“/”字符串替换'\\ /'的解决方案中使用

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

For iOS 13+ / macOS 10.15+ 适用于iOS 13+ / macOS 10.15+

You can use .withoutEscapingSlashes option to json decoder to avoid escaping slashes 您可以使用.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)
}

Console O/P 控制台O / P.

{"profileURL":" http://google.com ","username":"John"} {“profileURL”:“ http://google.com ”,“用户名”:“John”}


NOTE: As mention by Martin R in comments \\/ is a valid JSON escape sequence. 注:由于提马丁- [R在评论\\/是一个有效的JSON转义序列。

While playing around JSONEncoder/JSONDecoder, I found that the URL type is lossy on encode -> decode. 在JSONEncoder / JSONDecoder中玩游戏时,我发现编码 - >解码时URL类型是有损的。

Initializes with a string, relative to another URL. 使用字符串初始化,相对于另一个URL。

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

Might be help this apple document: https://developer.apple.com/documentation/foundation/url 可能会帮助这个苹果文档: https//developer.apple.com/documentation/foundation/url

using the PropertyList version, however: 但是,使用PropertyList版本:

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!! 希望对你有所帮助!!

Actually you cannot do that since in macOS and Linux are a bit different escaping systems. 实际上你不能这样做,因为在macOS和Linux中有一些不同的转义系统。 On linux // is allowed, macOS - not(it uses NSSerialization). 在linux //上是允许的,macOS - 不是(它使用NSSerialization)。 So, you can just add percent encoding on your string, which guarantees you equal strings on macOS and linux, right string posting to a server and right validating. 因此,您可以在字符串上添加百分比编码,这可以保证您在macOS和linux上使用相同的字符串,将字符串发布到服务器并正确验证。 On adding percent escaping set CharacterSet.urlHostAllowed . 在添加转义百分比时设置CharacterSet.urlHostAllowed Could be done like this: 可以这样做:

init(name: String, profile: String){
        username = name
        if let percentedString = profile.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlHostAllowed){
            profileURL = percentedString
        }else{
            profileURL = ""
        }
    }

In the same manner, you can removePercentEncoding AND YOU DONT NEED MODIFY SERVER SIDE!!! 以同样的方式,你可以删除PercentEncoding和你不需要修改服务器端!!!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM