30

我有以下代码:

import Foundation

let jsonData = """
[
    {"firstname": "Tom", "lastname": "Smith", "age": "28"},
    {"firstname": "Bob", "lastname": "Smith"}
]
""".data(using: .utf8)!

struct Person: Codable {
    let firstName, lastName: String
    let age: String?

    enum CodingKeys : String, CodingKey {
        case firstName = "firstname"
        case lastName = "lastname"
        case age
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        firstName = try values.decode(String.self, forKey: .firstName)
        lastName = try values.decode(String.self, forKey: .lastName)
        age = try values.decode(String.self, forKey: .age)
    }

}

let decoded = try JSONDecoder().decode([Person].self, from: jsonData)
print(decoded)

问题是它正在崩溃age = try values.decode(String.self, forKey: .age)。当我取出该init功能时,它工作正常。错误是No value associated with key age (\"age\").

关于如何使它成为可选并且在它不存在时不让它崩溃的任何想法?由于其他原因,我还需要该init功能,但只是做了一个简单的例子来解释发生了什么。

4

4 回答 4

94

年龄是可选的:

let age: String? 

所以尝试以这种方式解码:

let age: String? = try values.decodeIfPresent(String.self, forKey: .age)
于 2017-10-13T11:03:17.693 回答
1

在我的模型中,我所做的是

var title: String?

...

title = try container.decode(String?.self, forKey: .age)

而不是

name = try? container.decode(String.self, forKey: .age)

例如,出于某种原因,后端为该键传递了一个数值,例如title: 74. 使用第一种方法,你会得到这样的错误信息(我为我的模型写了一个单元测试),你可以快速定位问题

在此处输入图像描述

但是,使用第二种方法try?,这个有用的错误消息将被静音并且不会冒泡。你仍然会得到一个有效的解码结果title = nil,这在大多数情况下实际上是不正确的,如果只是null从后端应该产生一个nil.

但是当然,如​​果你设计的是无论从后端检索什么,只要类型不匹配,它就会是一个nil. 那么我认为第一种方法应该没有任何问题。

于 2020-06-17T17:11:23.383 回答
-1

iOS 有一个内置方法,仅当它们存在时才读取它们。

变量年龄:字符串?

年龄 = 尝试 container.decodeIfPresent(String.self, forKey: .age)

于 2021-05-26T19:59:05.213 回答
-3

这对我来说是工作。

var age: String? = nil
age = try? container.decode(String.self, forKey: .age)

希望得到帮助。

于 2018-01-02T03:22:11.797 回答