复杂JSON到Swift

复杂JSON到Swift,json,swift,Json,Swift,因此,我对JSON和将其转换为Swift比较陌生。我只处理了简单数据类型的基本JSON。没什么特别的。我还只讨论了如何使用我创建的JSON 现在我正在尝试使用从JSON和API收集的JSON。此JSON在其他对象中嵌套了对象 以下是JSON的格式: { "records": [ { "id": "Info", "fields": { "Card

因此,我对JSON和将其转换为Swift比较陌生。我只处理了简单数据类型的基本JSON。没什么特别的。我还只讨论了如何使用我创建的JSON

现在我正在尝试使用从JSON和API收集的JSON。此JSON在其他对象中嵌套了对象

以下是JSON的格式:

{
"records": [
    {
        "id": "Info",
        "fields": {
            "Card Name": "Info",
            "Qty": 0,
            "Card Type": "Info",
            "Color": "Info",
            "Card #": "Info",
            "Rarity": "Info",
            "Image": [
                {
                    "id": "Info",
                    "url": "url",
                    "filename": "info",
                    "size": 0,
                    "type": "info",
                    "thumbnails": {
                        "small": {
                            "url": "url",
                            "width": 0,
                            "height": 0
                        },
                        "large": {
                            "url": "url",
                            "width": 0,
                            "height": 0
                        },
                        "full": {
                            "url": "url",
                            "width": 0,
                            "height": 0
                        }
                    }
                }
            ],
            "Level": 0,
            "Full Set": 0
        },
        "createdTime": "info"
    }
],
"offset": "info"
}
我不确定我是否需要对“记录”部分做些什么。现在“记录”数组中有更多的记录

我不需要每个记录中的所有信息

我试过这样做:

struct Card {
    let offSet: String
    let cardName: String
}

extension Card: Decodable {
    enum CodingKeys: String, CodingKey {
        case offSet
        case cardName
        
        enum FieldKeys: String, CodingKey {
                case cardName = "Card Name"
            }
    }
    
    
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        offSet = try container.decode(String.self, forKey: .offSet)
        
        let fieldContainer = try container.nestedContainer(keyedBy: CodingKeys.FieldKeys.self, forKey: .cardName)
        cardName = try fieldContainer.decode(String.self, forKey: .cardName)
    }
    
}
每次我试着将信息解码到我的Swift结构中,结果都是零。我不知道我做错了什么,也不知道该怎么办。我没有处理过有“记录”的JSON:设置如下。不知道这是否重要


还有一个关于图像的附带问题。我会使用url属性来显示图像吗?图像文件将是PNG。以前从未处理过图像和JSON。

正如Larme评论的那样,“您的代码无法猜测”——这意味着您需要在代码中表示JSON提供的相同结构

在为您做这项工作的危险中,我已经编写了一套非常详细的
Codable
struct
,从您提供的JSON中提取所有数据

struct Card: Codable {
    var records:[Record]
    var offset:String
}

struct Record: Codable {
    var id:String
    var fields:Fields
    var createdTime:String
}

struct Fields: Codable {
    var name:String
    var quantity:Int
    var type:String
    var color:String
    var number:String
    var rarity:String
    var level:Int
    var fullSet:Int
    var image:[Image]
    enum CodingKeys: String, CodingKey {
        case name = "Card Name"
        case quantity = "Qty"
        case type = "Card Type"
        case color = "Color"
        case number = "Card #"
        case rarity = "Rarity"
        case level = "Level"
        case fullSet = "Full Set"
        case image = "Image"
    }
}

struct Image: Codable {
    var id:String
    var url:String
    var filename:String
    var size:Int
    var type:String
    var thumbnails:Thumbnails
}

struct Thumbnails: Codable {
    var small:Thumbnail
    var large:Thumbnail
    var full:Thumbnail
}

struct Thumbnail: Codable {
    var url:String
    var width:Int
    var height:Int
}
我在一个操场上测试了上述内容,将您提供的JSON粘贴为多行字符串,并使用以下命令转储生成的对象

do {
    if let data = json.data(using: .utf8) {
        let card = try JSONDecoder().decode(Card.self, from: data)
        dump(card)
    }
} catch {
    fatalError("Failed to decode \(error)")
}
其产出为:

▿ __lldb_expr_21.Card
  ▿ records: 1 element
    ▿ __lldb_expr_21.Record
      - id: "Info"
      ▿ fields: __lldb_expr_21.Fields
        - name: "Info"
        - quantity: 0
        - type: "Info"
        - color: "Info"
        - number: "Info"
        - rarity: "Info"
        - level: 0
        - fullSet: 0
        ▿ image: 1 element
          ▿ __lldb_expr_21.Image
            - id: "Info"
            - url: "url"
            - filename: "info"
            - size: 0
            - type: "info"
            ▿ thumbnails: __lldb_expr_21.Thumbnails
              ▿ small: __lldb_expr_21.Thumbnail
                - url: "url"
                - width: 0
                - height: 0
              ▿ large: __lldb_expr_21.Thumbnail
                - url: "url"
                - width: 0
                - height: 0
              ▿ full: __lldb_expr_21.Thumbnail
                - url: "url"
                - width: 0
                - height: 0
      - createdTime: "info"
  - offset: "info"

一旦你有了所有的数据,你就可以开始简化事情了,也许是得到第一个记录名的卡片的扩展

extension Card {
    var cardName:String {
        guard let firstRecord = self.records.first else {
            return "Unknown Name"
        }
        return firstRecord.fields.name
    }
}

print(card.cardName) // "Info\n"

发生这种情况时,您的代码是什么?但是
记录
是一个数组(可能是多个值),发生这种情况时,您需要哪个
卡名
?你需要通过这个结构。你的代码猜不出字段
CardName
在记录之后,它可能在任何地方,也可能在字段之后。尝试在线工具将更快地为你生成它,通过练习,你将了解如何自己构造它,这基本上是遵循与响应相同的结构。使用中介结构进行解析会更容易。如果需要,您可以将它们设置为私有,并在顶层
struct
上添加一个
lazy var
,从中检索所需的值。对于延迟,我们深表歉意。这是我的业余爱好,忙碌的生活的一个附带项目。这是一个巨大的帮助。我能够以此作为指导方针。我还找到了一个教程。在我完全掌握它之前,我通常必须先看看事情是如何运作的。现在我可以进一步完善这个,事实证明,我不需要这些数据。所以我可以修改它,现在我有了一个更好的主意。我将生成不同的JSON结构并进行练习。伟大的起点!!!