如何在 swift 4 中将 JSON 文件转换为字典?

-1 swift

我将此 JSON 保存在文件(“list_catalog.json”)中:

[
 {
  "idcatalog": 1,
  "imgbase64": "",
  "urlImg": "http://172.../page01.jpg",
  "urlPages": "http://172.../catalog_1_pages.json",
  "dt_from": "",
  "dt_to": ""
 },
 {
  "idcatalog": 2,
  "imgbase64": "",
  "urlImg": "http://172.../1.jpg",
  "urlPages": "http://172.../2_pages.json",
  "category": [
   {
    "id": 1,
    "lib": "lib"
   }
  ],
  "dt_to": ""
 }
]
Run Code Online (Sandbox Code Playgroud)

我可以通过以下方式获取该文件:

if let url = URL(string: "http://172.../list_catalogs.json") {
        do {
            let contents = try String(contentsOf: url)
            print(contents)

        } catch {
            // contents could not be loaded
        }
    }
Run Code Online (Sandbox Code Playgroud)

但我无法在字典中转换这个字符串。为了将数据转换为字符串,我使用这个函数:

func convertToDictionary(text: String) -> [String: Any]? {
    if let data = text.data(using: .utf8) {
        do {
            return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
        } catch {
            print(error.localizedDescription)
        }
    }
    return nil
}
Run Code Online (Sandbox Code Playgroud)

但对于这种情况,它不起作用有人可以帮助我吗?

Scr*_*ble 6

您所拥有的代码的问题是您正在尝试将数组转换为字典(正如在撰写本文时 Vadian、Moritz 的评论中几个人正确指出的那样)。

因此,显而易见的第一步解决方案是不要强制转换为[String: Any][[String: Any]]字典数组),但这仍然会给您带来该Any部分的问题。要使用此字典,您需要了解/记住键及其类型,并在使用时转换每个值。

最好使用Codable协议,它与解码器一起允许您基本上将 JSON 映射到相关的代码结构。

下面是如何使用 Swift 4 可编码协议解析此 JSON 的示例(在 Swift Playground 中完成)

let jsonData = """
[{
    "idcatalog": 1,
    "imgbase64": "",
    "urlImg": "http://172.../page01.jpg",
    "urlPages": "http://172.../catalog_1_pages.json",
    "dt_from": "",
    "dt_to": ""
}, {
    "idcatalog": 2,
    "imgbase64": "",
    "urlImg": "http://172.../1.jpg",
    "urlPages": "http://172.../2_pages.json",
    "category": [{
        "id": 1,
        "lib": "lib"
    }],
"dt_to": ""
}]
""".data(using: .utf8)!

struct CatalogItem: Codable {
    let idCatalog: Int
    let imgBase64: String?
    let urlImg: URL
    let urlPages: URL
    let dtFrom: String?
    let dtTo: String?
    let category: [Category]?

    enum CodingKeys: String, CodingKey {
        case idCatalog = "idcatalog"
        case imgBase64 = "imgbase64"
        case urlImg, urlPages, category
        case dtFrom = "dt_from"
        case dtTo = "dt_to"
    }
}

struct Category: Codable {
    let id: Int
    let lib: String?

    enum CodingKeys: String, CodingKey {
        case id, lib
    }
}

do {
    let decoder = JSONDecoder()
    let result = try decoder.decode([CatalogItem].self, from: jsonData)
    print(result)
} catch {
    print(error)
}
Run Code Online (Sandbox Code Playgroud)

控制台输出:

[__lldb_expr_118.CatalogItem(idCatalog:1,imgBase64:可选(“”),urlImg:http://172.../page01.jpg,urlPageshttp://172.../catalog_1_pages.json,dtFrom:可选(“”),dtTo:可选(“”),类别:nil),__lldb_expr_118.CatalogItem(idCatalog:2,imgBase64:可选(“”),urlImg:http ://172.../1.jpg,urlPageshttp://172.../2_pages.json,dtFrom:nil,dtTo:可选(“”),类别:可选([__lldb_expr_118.Category(id:1,lib:可选(“lib”))]) )]

现在好部分来了,现在使用这些数据更容易了......

print(result.first?.urlImg)
Run Code Online (Sandbox Code Playgroud)

输出:

可选(http://172.../page01.jpg

这适用于您提供的示例 JSON,但可能需要根据数据集的其余部分进行更多调整。