Быстрая стирание строк при сериализации в JSON с использованием Codable

Я пытаюсь сериализовать свой объект следующим образом:

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 была строго неэкранированной.

Ответ 1

В итоге я использовал 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)
}

Ответ 2

Я понял. Дело в том, что он не содержал никакого символа. Это просто свойство быстрого, чтобы он всегда возвращал такую ​​строку на консоли. Обходной путь заключается в том, чтобы j-son проанализировал его.

Тем не менее, вы можете использовать ниже решение для замены '\/' на строку "/"

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

Ответ 3

Для 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"}


ПРИМЕЧАНИЕ: Как упомянуто Мартином R в комментариях \/, это допустимая escape-последовательность JSON.

Ответ 4

Во время воспроизведения JSONEncoder/JSONDecoder, Я обнаружил, что тип URL имеет потерю при кодировании → декодирование.

Инициализирует строку по отношению к другому URL.

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

Возможно, вам поможет этот документ яблока: 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]))

Надеюсь, вам будет полезно!

Ответ 5

На самом деле вы не можете этого сделать, поскольку в macOS и Linux немного разные экранирующие системы. В linux//разрешен, macOS - нет (он использует NSSerialization). Таким образом, вы можете просто добавить процентную кодировку в свою строку, что гарантирует вам равные строки на macOS и linux, правильную проводку строки на сервер и правильную проверку. При добавлении процента сбрасывания установите CharacterSet.urlHostAllowed. Это можно сделать следующим образом:

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

Таким же образом вы можете удалитьPercentEncoding И ВАМ НЕОБХОДИМО ИЗМЕНИТЬ СТОРОНУ СЕРВЕР!!!