【问题标题】:Processing JSON using Swift JSONDecoder使用 Swift JSONDecoder 处理 JSON
【发布时间】:2018-12-19 19:23:26
【问题描述】:

这是我要解析的 JSON

{
  "rows": [
    {
      "layout": "Y",
    },
    {
      "layout": "A",
    }
  ]
}

我希望能够过滤掉不受支持的布局类型。我正在使用 JSONDecoder 将 JSON 数据转换为结构,但在处理行时遇到问题。我正在尝试使用 let row = try? 转换每一行rowContainer.decode(Row.self) 但我可以弄清楚如果它失败了如何移动到下一个,除非我将它解码为一个空结构。我尝试将其解码为字典,但除了值字段的 Any 之外,它不会。

enum RowType: String, Codable {
    case a = "A"
    case b = "B"
}

public struct Page: Codable {

    let rows: [Row]

    public init(from decoder: Decoder) throws {

        // Get Container
        let container = try decoder.container(keyedBy: CodingKeys.self)

        // Create Result Array
        var rowResult: [Row] = []

        // Get Rows Container
        var rowContainer = try container.nestedUnkeyedContainer(forKey: .rows)

        // Process Rows
        while !rowContainer.isAtEnd {

            // Create Row
            if let row = try? rowContainer.decode(Row.self) {
                rowResult.append(row)
            }
            else {

                // Increment Row Container
                _ = try rowContainer.decode(Empty.self)
            }
        }

        // Set Result
        rows = rowResult
    }

    // Used For Unsupported Rows
    struct Empty: Codable {}
}

public struct Row: Codable {
    let layout: RowType
}

【问题讨论】:

    标签: json swift struct codable jsondecoder


    【解决方案1】:

    这是一种不同的方法。

    使用layout 字符串值创建一个临时结构

    public struct RawRow: Codable {
        let layout: String
    }
    

    Page 中,首先将rows 解码为RawRow,然后将compactMap 数组解码为Row。它过滤所有layout值不能转换为枚举的项目

    public struct Page: Codable {
        let rows: [Row]
    
        public init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            let rowData = try container.decode([RawRow].self, forKey: .rows)
            rows = rowData.compactMap {
                guard let rowType = RowType(rawValue: $0.layout) else { return nil }
                return Row(layout: rowType)
            }
        }
    }
    

    【讨论】:

    • 在这种情况下是否有任何理由使用类型别名 Codable 而不是 Decodable?
    • @Marcy 不,没有。其实Decodable 就足够了。我刚刚复制并粘贴了结构。
    • 感谢@vadian 的澄清。
    • 这几乎是我在上面的代码中所做的,但我试图避免有这样的额外结构,但感谢您的回复
    • Empty 不也是一个额外的结构吗? ?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-05
    • 2019-11-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多