【问题标题】:Swifty JSON: convert hierarchical list of objects in JSON arrays to hierarchical Swift objectsSwifty JSON:将 JSON 数组中的对象分层列表转换为分层 Swift 对象
【发布时间】:2019-05-22 08:34:16
【问题描述】:

我有一个下面的 JSON 格式,它属于一个商店,在这个 json 对象内,Data 字段是一个 JSON 数组,由产品类别的层次结构组成,这些类别以嵌套的层次格式存储(每个类别都有子和每个孩子都可能有自己的孩子,等等)。

{"Data":[
            {"ID":1,"ParentCategoryId":0,"Name": "Parent1","Children":
                [
                    {"ID":2,"ParentCategoryId":1,"Name": "P1Child1","Children":[]},
                    {"ID":3,"ParentCategoryId":1,"Name": "P1Child2","Children":[]},
                    {"ID":4,"ParentCategoryId":1,"Name": "P1Child3","Children":[]},
                    {"ID":5,"ParentCategoryId":1,"Name": "P1Child4","Children":[]},
                ]
            },
            {"ID":6,"ParentCategoryId":0,"Name": "Parent2","Children":
                [
                    {"ID":7,"ParentCategoryId":6,"Name": "P2Child1","Children":[]},
                    {"ID":8,"ParentCategoryId":6,"Name": "P2Child2","Children":[]},
                    {"ID":9,"ParentCategoryId":6,"Name": "P2Child3","Children":[]}
                ]
            }
        ]
}

使用 Swifty JSON ussign json["Data"].array 读取此格式会返回一个没有层次结构的类别的平面列表。 我想知道如何在保留其结构的同时读取此分层 JSON 对象。 这是我的模型对象的当前结构(不包括 Children 归档,但必须修改为这样):

open class ProductCategory: NSObject {


    var idd                 :  NSInteger
    var name                :  String
    var parentCategoryId    :  NSInteger
    ...

}

【问题讨论】:

    标签: json swift swift4 hierarchical-data swifty-json


    【解决方案1】:

    这是使用Codable 建模的方法

    struct MyData: Codable {
        let data: [Datum]
    
        enum CodingKeys: String, CodingKey {
            case data = "Data"
        }
    }
    
    struct Datum: Codable {
        let id, parentCategoryID: Int
        let name: String
        let children: [Datum]
    
        enum CodingKeys: String, CodingKey {
            case id = "ID"
            case parentCategoryID = "ParentCategoryId"
            case name = "Name"
            case children = "Children"
        }
    }
    
    do {
        let myData = try JSONDecoder().decode(MyData.self, from: yourJsonData)
    } catch {
        print(error)
    }
    

    【讨论】:

    • @VSB 这种方法有什么问题?您究竟想如何设计模型?
    • @PGDev 我的方法没有问题。 -1 不是我的!但我仍在寻找其他可能的答案,这些答案需要对我的代码库进行较少的更改。
    • @VSB 你的“代码库”是什么?您能否改进/澄清您的问题,以便我们更好地了解您希望从解决方案中获得什么?
    • @JoakimDanielson 我的 API 调用中的响应由 Swifty JSON 解析,模型基于此场景。我不想重写我的所有请求/响应以使它们适合 Codable 并摆脱 Swifty JSON。我不知道这是否是一个好的偏好,因为我是 iOS 和 Swift 的新手,但是在 android 环境中使用 Retrofit 和 GSON 做这样的事情很简单,就像这个答案对Codables 所做的一样。但我想知道是否只能使用 Swifty JSON。
    • 最好开始使用Codable 而不是第三方库。它更加高效和可读。
    【解决方案2】:

    如果您可以考虑从 swiftyjson 迁移到 JSONSerialization,则以下内容应为您提供您所追求的结构

    do {
        if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] {
            if let categories = json["Data"] as? [[String: Any]] {            
              //map data to your classes here
            }
        }
    } catch {
        print("Decode failed: \(error)")
    }
    

    【讨论】:

      【解决方案3】:

      如果你使用Codable,你不需要SwiftyJSON,你可以这样做:

              do {
                  let productsData = try JSONDecoder().decode(ProductsDataResponse.self, from: (jsonString.data(using: .utf8))!)
              } catch let e {
                  print("Couldn't Parse data because... \(e)")
              }
      

      ProductsDataResponse 在哪里:

      struct ProductsDataResponse: Codable {
          let data: [ProductCategory]
      
          enum CodingKeys: String, CodingKey {
              case data = "Data"
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2021-11-12
        • 1970-01-01
        • 2021-07-15
        • 2015-04-14
        • 2021-10-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多