在 Swift 4 中导致 JSON 解码失败的可选 URL
Optional URLs causing JSON decoding to fail in Swift 4
我想弄清楚为什么使用 Optional URLs 会导致我的 JSON 使用 Swift 解码失败 4. 我已经在 WWDC 上倾诉过 "Whats new in Foundation" 视频、Apples Playground 示例以及互联网上的许多地方,但尚未找到解决方案。
这是我创建的一个测试来说明这个问题。假设这是我的 json 数据:
let json = """
{
"kind" : "",
"total" : 2,
"image_url" : "https://www.myawesomeimageURL.com/awesomeImage.jpg"
}
""".data(using: .utf8)!
这是我的结构:
struct BusinessService: Decodable {
let kind: String?
let total: Int
let image_url : URL?
}
这是我序列化它的地方:
let myBusiness = try? JSONDecoder().decode(BusinessService.self, from: json)
print(myBusiness)
现在,问题是如果我收到 json 数据,其中 image_url 丢失,json 解码失败并返回 nil。
我很困惑为什么 "kind" 可以是一个可选的字符串并且当它没有值时不会导致 json 解码失败,而 image_url 不能是一个可选的 URL 而不会导致 json 失败。
两天来我一直在努力解决这个问题,但没有成功。有谁知道为什么会失败?
我确实注意到了另一个难题,那就是 json 中的 image_url 实际上不一定是有效图像 URL。我可以输入任何字符串并且我的结构被序列化,所以我想我可能误解了它是如何工作的。我认为 URL 仅当它可以转换为有效的 URL 时才会自动填充,而这并没有发生。
任何对此的见解将不胜感激。
这符合我的预期。将 image_url
设置为 null
或将其完全省略会导致有效的 BusinessService
被解码为 image_url
字段的 nil
值:
struct Example: Decodable {
let url: URL?
}
// URL is present. This works, obviously.
try JSONDecoder().decode(Example.self, from: """
{ "url": "foo" }
""".data(using: .utf8)!)
// URL is missing, indicated by null. Also works.
try JSONDecoder().decode(Example.self, from: """
{ "url": null }
""".data(using: .utf8)!)
// URL is missing, not even the key is present. Also works.
try JSONDecoder().decode(Example.self, from: """
{}
""".data(using: .utf8)!) // works, too
唯一的麻烦出现在我为字段提供无效的 URL 值(例如空字符串)时。所以我想这是你的问题?
// This throws: "Invalid URL string."
try JSONDecoder().decode(Example.self, from: """
{ "url": "" }
""".data(using: .utf8)!)
您必须通过发送 null
或保留整行来为 URL 字段发送“none”值,而不是发送空字符串。
I am confused as to why "kind" can be an optional string and not cause the json decoding to fail when it has no value, yet image_url cannot be an optional URL without causing the json to fail.
不同之处在于 JSON 中的 ""
是有效的 String
值,而不是有效的 URL.
我们可以通过一个简单的调整来处理这种情况。您可以使用 try catch 块来解码 url 项。如果存在Invalid URL Case,那么我们可以在try catch块中赋null值。
struct Example: Codable {
let url: URL?
private enum CodingKeys: String, CodingKey {
case url
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
do {
url = try container.decode(URL.self, forKey: .url)
}catch( _) {
url = nil
}
}
}
注意:在 swift playground 中,上面的代码仍然会导致崩溃,但它在常规 Xcode 项目
我想弄清楚为什么使用 Optional URLs 会导致我的 JSON 使用 Swift 解码失败 4. 我已经在 WWDC 上倾诉过 "Whats new in Foundation" 视频、Apples Playground 示例以及互联网上的许多地方,但尚未找到解决方案。
这是我创建的一个测试来说明这个问题。假设这是我的 json 数据:
let json = """
{
"kind" : "",
"total" : 2,
"image_url" : "https://www.myawesomeimageURL.com/awesomeImage.jpg"
}
""".data(using: .utf8)!
这是我的结构:
struct BusinessService: Decodable {
let kind: String?
let total: Int
let image_url : URL?
}
这是我序列化它的地方:
let myBusiness = try? JSONDecoder().decode(BusinessService.self, from: json)
print(myBusiness)
现在,问题是如果我收到 json 数据,其中 image_url 丢失,json 解码失败并返回 nil。
我很困惑为什么 "kind" 可以是一个可选的字符串并且当它没有值时不会导致 json 解码失败,而 image_url 不能是一个可选的 URL 而不会导致 json 失败。
两天来我一直在努力解决这个问题,但没有成功。有谁知道为什么会失败?
我确实注意到了另一个难题,那就是 json 中的 image_url 实际上不一定是有效图像 URL。我可以输入任何字符串并且我的结构被序列化,所以我想我可能误解了它是如何工作的。我认为 URL 仅当它可以转换为有效的 URL 时才会自动填充,而这并没有发生。
任何对此的见解将不胜感激。
这符合我的预期。将 image_url
设置为 null
或将其完全省略会导致有效的 BusinessService
被解码为 image_url
字段的 nil
值:
struct Example: Decodable {
let url: URL?
}
// URL is present. This works, obviously.
try JSONDecoder().decode(Example.self, from: """
{ "url": "foo" }
""".data(using: .utf8)!)
// URL is missing, indicated by null. Also works.
try JSONDecoder().decode(Example.self, from: """
{ "url": null }
""".data(using: .utf8)!)
// URL is missing, not even the key is present. Also works.
try JSONDecoder().decode(Example.self, from: """
{}
""".data(using: .utf8)!) // works, too
唯一的麻烦出现在我为字段提供无效的 URL 值(例如空字符串)时。所以我想这是你的问题?
// This throws: "Invalid URL string."
try JSONDecoder().decode(Example.self, from: """
{ "url": "" }
""".data(using: .utf8)!)
您必须通过发送 null
或保留整行来为 URL 字段发送“none”值,而不是发送空字符串。
I am confused as to why "kind" can be an optional string and not cause the json decoding to fail when it has no value, yet image_url cannot be an optional URL without causing the json to fail.
不同之处在于 JSON 中的 ""
是有效的 String
值,而不是有效的 URL.
我们可以通过一个简单的调整来处理这种情况。您可以使用 try catch 块来解码 url 项。如果存在Invalid URL Case,那么我们可以在try catch块中赋null值。
struct Example: Codable {
let url: URL?
private enum CodingKeys: String, CodingKey {
case url
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
do {
url = try container.decode(URL.self, forKey: .url)
}catch( _) {
url = nil
}
}
}
注意:在 swift playground 中,上面的代码仍然会导致崩溃,但它在常规 Xcode 项目