首页 文章

使用Swift JSONDecoder处理JSON

提问于
浏览
1

这是我试图解析的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
}

1 回答

  • 4

    这是一种不同的方法 .

    使用 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)
            }
        }
    }
    

相关问题