【问题标题】:Decoding/parsing specific JSON with Swift使用 Swift 解码/解析特定的 JSON
【发布时间】:2018-05-08 10:55:20
【问题描述】:

我在尝试使用 Swift 4 解码这个 JSON 时遇到了很多麻烦。

{
    "Items": [
        {
            "id": 1525680450507,
            "animal": "bee",
            "type": "insect",
            "diet": [
                "a",
                "b",
                "c"
            ]
        }
    ],
    "Count": 1,
    "ScannedCount": 5
}

这是我尝试解码的地方

let decoder = JSONDecoder()
let data = try decoder.decode([Animal].self, from: data)

我已经创建了一个这样的结构

struct Animal: Codable {
    var id: Int
    var animal: String
    var type: String
    var diet: [String]
}

let decoder = JSONDecoder()
let data = try decoder.decode(ItemsResponse.self, from: data)

这不起作用。我收到一条错误提示

“应解码 Array,但找到了字典。”

所以我想也许我需要这样的东西

struct ItemsResponse: Codable {
    var Items: [Animal]
    var Count: Int
    var ScannedCount: Int
}

但这也不起作用。现在我明白了

“应解码 Array,但找到了一个字符串/数据。”

如何制作一个可以解码这个 JSON 的结构体?

【问题讨论】:

  • 使用您提供的最后两条代码,我可以在 Playground 上使用它。也许您正在尝试“真正的 JSON”(不仅仅是那个示例),并且有一个可选值(例如,如果没有找到不同类型的值)。
  • 你的代码是对的,它在我这边工作
  • 这是我从邮递员那里得到的响应,当我打印出我在 Swift 中返回的 json 时,它看起来是一样的。但我仍然会收到错误消息。完整的错误是这个 Err typeMismatch(Swift.Array, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "Items", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0) , CodingKeys(stringValue: "diet", intValue: nil)], debugDescription: "预期解码 Array 但找到了一个字符串/数据。",底层错误: nil))
  • 哦,这是因为在 Items 数组中我有其他没有饮食的对象作为字符串数组,它只有 1 个字符串。我只发布了其中一个示例。一旦我纠正了这一点,一切正常。感谢您确认我的代码有效。

标签: ios json swift


【解决方案1】:
let data = try decoder.decode([Animal].self, from: data)

[Animal].self 不正确,您可以这样使用:

struct DataJson: Codable {
    let items: [Item]
    let count, scannedCount: Int

    enum CodingKeys: String, CodingKey {
        case items = "Items"
        case count = "Count"
        case scannedCount = "ScannedCount"
    }
}

struct Item: Codable {
    let id: Int
    let animal, type: String
    let diet: [String]
}

// MARK: Convenience initializers

extension DataJson {
    init(data: Data) throws {
        self = try JSONDecoder().decode(DataJson.self, from: data)
    }



    func jsonData() throws -> Data {
        return try JSONEncoder().encode(self)
    }

    func jsonString(encoding: String.Encoding = .utf8) throws -> String? {
        return String(data: try self.jsonData(), encoding: encoding)
    }
}

extension Item {
    init(data: Data) throws {
        self = try JSONDecoder().decode(Item.self, from: data)
    }


    func jsonData() throws -> Data {
        return try JSONEncoder().encode(self)
    }

    func jsonString(encoding: String.Encoding = .utf8) throws -> String? {
        return String(data: try self.jsonData(), encoding: encoding)
    }
}

【讨论】:

    【解决方案2】:

    试试这个:

    import Foundation
    
    let json = """
    {
        "Items": [
            {
                "id": 1525680450507,
                "animal": "bee",
                "type": "insect",
                "diet": [
                    "a",
                    "b",
                    "c"
                ]
            }
        ],
        "Count": 1,
        "ScannedCount": 5
    }
    """
    
    struct Animal: Codable {
        var id: Int
        var animal: String
        var type: String
        var diet: [String]
    }
    
    struct ItemsResponse: Codable {
        var Items: [Animal]
        var Count: Int
        var ScannedCount: Int
    }
    
    let data = try! JSONDecoder().decode(ItemsResponse.self, from: json.data(using: .utf8)!)
    

    当然,您应该妥善处理可能的故障(即不要执行try!,也不要强制解开json.data()! 部分)

    但上面的代码有效,希望能回答你的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多