【问题标题】:How to parse a JSON array of arrays and refer to the members of the inner array by names?如何解析数组的 JSON 数组并按名称引用内部数组的成员?
【发布时间】:2021-12-21 15:38:43
【问题描述】:

Swift Playground 中,我尝试解析以下数据:

let jsonMoves:String =

"""
{ "moves":
    [
        [0, 'CAT (7)', 'ACT'],
        [1, 'EXTRA (14)', 'ERXT'],
        [0, 'TOP (22)', 'PO'],
        [1, 'TOY (9)', 'Y']
    ]
 }
"""

为此,我创建了 2 个结构:

struct MovesResponse: Codable {
    let moves: [[MoveModel]]
}

struct MoveModel: Codable {
    let mine: Int
    let words: String
    let letters: String
}

还有电话:

let decoder = JSONDecoder()

if let movesData = jsonMoves.data(using: .utf8),
   let movesModel = try? decoder.decode(MovesResponse.self, from: movesData),
   movesModel.count > 0 // does not compile
{
    print("Parsed moves: ", movesModel)
} else {
    print("Can not parse moves")
}

不幸的是,上面的代码给了我编译错误:

“MovesResponse”类型的值没有成员“count”

当我删除该行并将try? 更改为try! 以查看异常时,我得到了错误:

致命错误:“试试!”表达式意外引发错误: Swift.DecodingError.dataCorrupted(Swift.DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value第 3 行第 12 列附近。" UserInfo={NSDebugDescription=第 3 行第 12 列附近的无效值。NSJSONSerializationErrorIndex=29})))

作为 Swift 新手,我认为结构 MoveModel 是错误的。请帮忙。

另外我想知道是否可以将内部数组的三个元素称为“我的”、“单词”、“字母”?

更新:

我已按照 Joakim 的建议将 jsonMoves 中的单引号更改为双引号(谢谢!),现在的错误是:

致命错误:“试试!”表达式意外引发错误:Swift.DecodingError.typeMismatch(Swift.Dictionary, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "moves", intValue: nil), _JSONKey(stringValue: "索引 0", intValue: 0), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "期望解码 Dictionary 但找到了一个数字。",底层错误:nil))

【问题讨论】:

  • 我认为在最里面的数组中应该是双引号而不是单引号?
  • 试试movesModel.moves.count > 0
  • 谢谢,我已将单引号更改为双引号 - 并使用新的错误消息更新了我的问题

标签: ios json swift jsondecoder arrayofarrays


【解决方案1】:

您可以使用MoveModel,但由于每个内部数组都代表MoveModel 的一个实例,您需要将第一个结构更改为

struct MovesResponse: Codable {
    let moves: [MoveModel]
}

然后您需要在MoveModel 中使用自定义init(from:) 将每个数组解码为MoveModel 对象,使用无键容器而不是编码键。

init(from decoder: Decoder) throws {
    var container = try decoder.unkeyedContainer()
    mine = try container.decode(Int.self)
    words = try container.decode(String.self)
    letters = try container.decode(String.self)
}

与其使用try? 并打印硬编码消息,我建议您捕获错误并打印它

let decoder = JSONDecoder()
do {
  let movesModel = try decoder.decode(MovesResponse.self, from: data)
    print(movesModel)
} catch {
    print(error)
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-09
    • 1970-01-01
    • 2017-06-10
    • 2020-02-15
    • 2021-09-25
    • 2020-04-16
    • 1970-01-01
    相关资源
    最近更新 更多