【问题标题】:JSON objects in Swift 5Swift 5 中的 JSON 对象
【发布时间】:2020-09-05 20:42:22
【问题描述】:

我正在尝试访问下面的 json api 中的数据

"Products": [
            {
                "ProductName": "GR",
                "ShortDescription": "General service epoxy mortar system that utilizes recycled glass and rapidly renewable soy based components.",
                "PDSOverride": [
                    {
                        "FileName": "EcoLab Netherlands",
                        "FileUrl": "http://test.stonhard.com/media/2264/eco-lab-netherlands-usa-version.pdf"
                    },
                    {
                        "FileName": "General Dynamics.pdf",
                        "FileUrl": "http://test.stonhard.com/media/2060/general-dynamics.pdf"
                    }
                ]
            }
        ]

我在下面这样的结构中对此进行建模

struct Solutions: Codable, Identifiable {
    let id = UUID()
    let SectionTitle: String
    let SectionImage: String
    let ProductLines: [ProductLine]
}

struct ProductLine: Codable {
    let System: String
    let Products: [Product]
}

struct Product: Codable {
    let ProductName: String
    let ShortDescription: String
    let PDSOverride: [PDSOverride]
}

struct PDSOverride: Codable {
    let FileName: String
    let FileUrl: String
}

struct SdsPdf: Codable {
    let FileName: String
    let FileUrl: String
}

struct GuideSpecPdf: Codable {
    let FileName: String
    let FileUrl: String
}   

当我尝试访问数据时,我收到一条错误消息,指出无法读取数据,因为它的格式不正确。我知道这是我的模型的问题,因为当我注释掉 PDSOverride、SdsPdf 和 GuideSpecPdf 时它可以工作,但显然我无权访问这些数据。如何对我的结构进行建模以便提取数据?

【问题讨论】:

  • 您发布的 JSON 不是有效的 JSON。那是您收到的完整 JSON 吗?如果没有,您能否发布完整 JSON 的一部分以使 JSON 仍然有效?
  • 转到 app.quicktype.io 并插入您的 JSON。它会为它构建一组结构,你可以将它们与你的比较,看看你的问题在哪里(或者你可以使用它生成的代码)

标签: ios json swift xcode swift5


【解决方案1】:

问题不在于您的模型,您的 JSON 格式错误,正如编译器所说,您的 JSON 需要如下所示:

[
    { 
        "Products": [
            {
                "ProductName": "GR",
                "ShortDescription": "General service epoxy mortar system that utilizes recycled glass and rapidly renewable soy based components.",
                "PDSOverride": [
                    {
                        "FileName": "EcoLab Netherlands",
                        "FileUrl": "http://test.stonhard.com/media/2264/eco-lab-netherlands-usa-version.pdf"
                    },
                    {
                        "FileName": "General Dynamics.pdf",
                        "FileUrl": "http://test.stonhard.com/media/2060/general-dynamics.pdf"
                    }
                ]
            }
        ]
    }
]

另外,模型也可以这样做,推荐你用Quicktype (https://app.quicktype.io) 在线版不错,有桌面版:

// MARK: - PurpleProduct
struct PurpleProduct: Codable {
    let products: [ProductProduct]

    enum CodingKeys: String, CodingKey {
        case products = "Products"
    }
}

// MARK: - ProductProduct
struct ProductProduct: Codable {
    let productName, shortDescription: String
    let pdsOverride: [PDSOverride]

    enum CodingKeys: String, CodingKey {
        case productName = "ProductName"
        case shortDescription = "ShortDescription"
        case pdsOverride = "PDSOverride"
    }
}

// MARK: - PDSOverride
struct PDSOverride: Codable {
    let fileName: String
    let fileURL: String

    enum CodingKeys: String, CodingKey {
        case fileName = "FileName"
        case fileURL = "FileUrl"
    }
}

typealias Products = [PurpleProduct]

要解码你可以使用 JSONDecoder,我也建议你在这个页面检查你的 json:https://jsonformatter.curiousconcept.com

【讨论】:

    【解决方案2】:

    假设您的 JSON 只缺少右大括号,您可以像这样解析它:

    struct Entry: Codable {
        let products: [Product]
    
        enum CodingKeys: String, CodingKey {
            case products = "Products"
        }
    }
    
    struct Product: Codable {
        let productName, shortDescription: String
        let pdsOverride: [PDSOverride]
    
        enum CodingKeys: String, CodingKey {
            case productName = "ProductName"
            case shortDescription = "ShortDescription"
            case pdsOverride = "PDSOverride"
        }
    }
    
    struct PDSOverride: Codable {
        let fileName: String
        let fileURL: String
    
        enum CodingKeys: String, CodingKey {
            case fileName = "FileName"
            case fileURL = "FileUrl"
        }
    }
    
    do {
        let entries = try JSONDecoder().decode([Entry].self, from: data)
    } catch {
        print(error)
    }
    
    

    【讨论】:

    • 您好,感谢您在这里帮助我。我仍然遇到同样的错误,但我猜这是因为我没有发布完整的代码。我试图只发布我需要帮助的内容,但这是一个坏主意。我现在要用完整的代码更新我的问题。
    • 您添加的代码确实不适合 JSON sn-p - 有很多缺失的属性。正如其他人已经建议的那样,获取完整的 JSON 并将其粘贴到 app.quicktype.io 以获得一个非常好的结构起点。另外:首字母大写通常保留给 Swift 中的类型名称,属性名称应以小写字母开头。使用CodingKeys 在两者之间进行映射,就像在我的示例中一样。
    猜你喜欢
    • 2020-05-08
    • 2019-10-28
    • 2020-05-27
    • 1970-01-01
    • 2021-06-16
    • 2020-03-30
    • 1970-01-01
    • 2020-09-22
    • 1970-01-01
    相关资源
    最近更新 更多