使用 SwiftyJSON 解析具有相似元素的 JSON

Posted

技术标签:

【中文标题】使用 SwiftyJSON 解析具有相似元素的 JSON【英文标题】:Parse JSON with similar elements using SwiftyJSON 【发布时间】:2018-10-16 17:14:55 【问题描述】:

我有这种类型的 JSON(只是一个简短的示例):

"orderProducts": [
        
            "id": 135,
            "order_id": 39,
            "product_id": 49,
            "product_code": "",
            "size_id": 13,
            "quantity": 2,
            "product": 
                "id": 49,
                "code": "",
                "factory_id": 2,
                "product_category_id": 1,
                "sex_id": null,
                "season_id": null,
                "product_type_id": null,
                "type_id": null,
                "color_id": null,
                "year_id": null,
                "image_1": "bceef8b28ae2a1797ca0c6300021100d.jpeg",
                "image_2": "",
                "image_3": "",
                "notes": "",
                "status": 10
            
        ,
        
            "id": 136,
            "order_id": 39,
            "product_id": 49,
            "product_code": "",
            "size_id": 14,
            "quantity": 3,
            "product": 
                "id": 49,
                "code": "",
                "factory_id": 2,
                "product_category_id": 1,
                "sex_id": null,
                "season_id": null,
                "product_type_id": null,
                "type_id": null,
                "color_id": null,
                "year_id": null,
                "image_1": "bceef8b28ae2a1797ca0c6300021100d.jpeg",
                "image_2": "",
                "image_3": "",
                "notes": "",
                "status": 10
            
        ,
        
            "id": 137,
            "order_id": 39,
            "product_id": 48,
            "product_code": "",
            "size_id": null,
            "quantity": 24,
            "product": 
                "id": 48,
                "code": "",
                "factory_id": 2,
                "product_category_id": null,
                "sex_id": null,
                "season_id": null,
                "product_type_id": null,
                "type_id": null,
                "color_id": null,
                "year_id": null,
                "image_1": "2aee8660b4218bf549c2d9345beb2a01.jpeg",
                "image_2": "",
                "image_3": "",
                "notes": "",
                "status": 10
            
        ]

我需要解析的项目是:product_idsize_idquantity。为此,我创建了这个结构:

struct Products 
    let id: String
    let quantities: [(sizeId: String, quantity: String)]?

    init(id: String, quantities: [(sizeId: String, quantity: String)]) 
        self.id = id
        self.quantities = quantities
    

我想要达到的最终结果是:

[Products(id: "49", quantities: [(sizeId: "13", quantity: "2"), (sizeId: "14", quantity: "3")]), 
Products(id: "48", quantities: [(sizeId: "null", quantity: "24")])]

使用 SwiftyJSON 解析时,我会这样做:

for productId in products.arrayValue 
                        self.productWithQuantites.append(Products(id: productId["product_id"].stringValue,
                                                                  quantities: [(sizeId: productId["size_id"].stringValue,
                                                                                quantity: productId["quantity"].stringValue)]))

                    

但我明白了:

    [Products(id: "49", quantities: [(sizeId: "13", quantity: "2")]),
Products(id: "49", quantities: [(sizeId: "14", quantity: "3")],
Products(id: "48", quantities: [(sizeId: "null", quantity: "24")])]

我做错了什么?如何将新数量附加到现有元素?非常感谢您提供代码示例或任何帮助。

【问题讨论】:

【参考方案1】:

在 Swift 4 中,SwiftyJSON 已过时,取而代之的是 Codable 协议。

不要在结构中使用元组,将值分开并根据产品 ID 将 Product(最好是单数形式)实例分组到字典中。

假设 data 包含 JSON 原始数据创建这些微小的结构

struct Root : Decodable 
    let orderProducts : [Product]


struct Product: Decodable 
    let id : Int
    let productId : Int
    let sizeId : Int?

将 JSON 解码为结构体并使用 Dictionary(grouping:by:) 对数组进行分组

do 
   let decoder = JSONDecoder()
   decoder.keyDecodingStrategy = .convertFromSnakeCase
   let result = try decoder.decode(Root.self, from: data)
   let groupedDictionary = Dictionary(grouping: result.orderProducts, by: $0.productId)
   print(groupedDictionary)
   // [49: [Product(id: 135, productId: 49, sizeId: Optional(13)), 
   //      Product(id: 136, productId: 49, sizeId: Optional(14))], 
   //  48: [Product(id: 137, productId: 48, sizeId: nil)]]

 catch  print(error) 

【讨论】:

嗨,谢谢你的帮助,但是我的项目到处都在使用 SwiftyJSON,所以我必须坚持下去 我强烈建议升级Codable。效率更高。 我会,在我的下一个项目中。感谢您的帮助。【参考方案2】:

为了在这样的循环中更容易修改,您应该将Products 设为一个类,因为它是通过引用传递的。另外,将quantities 设为var 在您的Products 中,并将解析代码替换为:

for product in products.arrayValue 
    let productId = product["product_id"].stringValue

    let quantity = (sizeId: product["size_id"].stringValue,
                    quantity: product["quantity"].stringValue)

    if let product = self.productWithQuantites.filter( $0.id == productId ).first 
        product.quantities?.append(quantity)
     else 
        self.productWithQuantites.append(Products(id: productId, quantities: [quantity]))
    

此代码将一个新元组附加到现有产品的quantities 属性,或者如果它不存在,它会创建一个新的Products 并将其附加到productWithQuantites

【讨论】:

您好,感谢您的建议,但我在这里遇到错误:product.quantities.append(quantity) - Value of type '[(sizeId: String, quantity: String)]?' has no member 'append' @TarasTomchuk 对不起,我错过了一个问号。它应该是product.quantities?.append(quantity),因为quantities 是可选的。 @ Tamás Sengel 另外,if let product 应更改为 if var product,因为它会在产品被出租时引发错误。但是,我在这里得到的输出是:[Products(id: "49", quantities: Optional([(sizeId: "13", quantity: "2")])), Products(id: "48", quantities: Optional([(sizeId: "", quantity: "24")]))] 所以,它似乎没有添加其他数量 糟糕,我的错;我没有意识到 Products 是一个 struct 而不是一个类。由于类是通过引用传递的,因此在这样的循环中修改它们要容易得多。我建议将Products 设为一个类。 改成一个类,现在我的输出是这样的——[Products, Products]【参考方案3】:

这样接收是正常的,因为在你的 JSON 中有两个条目,"product_id": 49

因此,您可以在解析 json 后,通过在多次找到相同项目时删除两个 for 循环来解决它,如下所示:

for i in 0..<productWithQuantites.count 
        for j in 0..<productWithQuantites.count 
            if productWithQuantites[i].productID == productWithQuantites[j].productID 
                productWithQuantites.remove(at: j)
            
        
    

【讨论】:

【参考方案4】:

您应该将 Alamofire 与 JSONDecoder 一起使用,而不是 swiftyjson 和更多参考资料,您可以观看此链接https://m.youtube.com/watch?v=YY3bTxgxWss上提供的此视频

【讨论】:

以上是关于使用 SwiftyJSON 解析具有相似元素的 JSON的主要内容,如果未能解决你的问题,请参考以下文章

尝试使用 swiftyJSON 快速解析 JSON

在 SwiftUI 上迭代 JSON 数组(使用 SwiftyJson 解析)

SwiftyJSON - 解析时如何遍历子节点

将 SwiftyJSON 中的元素添加到 Swift 中的 URL 数组

使用 SwiftyJSON 选择字符串数组

使用 SwiftyJSON 解析 JSON