Экранирование строки Swift при сериализации в 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 вернуть неоткрытую форму на macOS?
мне нужна строка в JSON, чтобы быть строго без эскапады.
4 ответов
Я закончил с помощью 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)
}
Я понял. Дело в том, что в нем не было никакого характера. Это просто свойство swift, что он всегда будет возвращать такую строку на консоли. Обходной путь-это разбор j-son.
тем не менее, вы можете использовать ниже Решение замены '\/' на "/" string
let newString = str.replacingOccurrences(of: "\/", with: "/")
print(newString)
во время игры вокруг JSONEncoder / JSONDecoder,
Я обнаружил, что URL
тип с потерями на encode - > decode.
инициализируется строкой относительно другого URL-адреса.
init?(string: String, relativeTo: URL?)
может помочь этот документ apple: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]))
надеюсь, что будет полезно для вас!!
На самом деле вы не можете этого сделать, так как в macOS и Linux немного разные экранирующие системы. На linux / / разрешено, macOS-нет (он использует NSSerialization). Таким образом, вы можете просто добавить процентную кодировку в свою строку, что гарантирует вам равные строки в macOS и linux, правильную публикацию строки на сервере и правильную проверку. При добавлении процента escaping set CharacterSet.urlHostAllowed
. Можно было бы сделать так:
init(name: String, profile: String){
username = name
if let percentedString = profile.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlHostAllowed){
profileURL = percentedString
}else{
profileURL = ""
}
}
таким же образом, вы можете removePercentEncoding И ВАМ НЕ НУЖНО ДОРАБОТАТЬ НА СТОРОНЕ СЕРВЕРА!!!