Parse JSON with similar elements using SwiftyJSON

烂漫一生 提交于 2019-12-11 15:40:54

问题


I have this type of JSON (just a short sample):

"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
            }
        }]

Items I need to parse are: product_id, size_id and quantity. For this, I have created this struct:

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
    }
}

The end result I'm trying to achieve is:

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

When parsing using SwiftyJSON, I do this:

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

                    }

But I get this:

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

What I'm doing wrong? How can I append new quantities to my existing elements? Would be thankful for a code sample or any help.


回答1:


For easier modification in loops like this, you should make Products a class, since it's passed by reference. Also, make quantities to a var in your Products and replace the parsing code to this:

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]))
    }
}

This code appends a new tuple to the quantities property of an existing product, or if it does not exist, it creates a new Products and appends that to productWithQuantites.




回答2:


In Swift 4 SwiftyJSON became obsolete in favor of the Codable protocol.

Don't use tuples in structs, separate the values and group the Product (singular form is preferable) instances into a dictionary depending on the product id.

Assuming data contains the JSON raw data create these tiny structs

struct Root : Decodable {
    let orderProducts : [Product]
}

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

Decode the JSON into the structs and group the array with 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) }



回答3:


Its normal to receive like that, since in your JSON there are two entries, with "product_id": 49

So you can solve it as, after parsing your json, by having two for loops to remove once you find the same item more than once as following:

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



回答4:


You should use Alamofire with JSONDecoder instead swiftyjson and more reference you can watch this video which is available on this link https://m.youtube.com/watch?v=YY3bTxgxWss



来源:https://stackoverflow.com/questions/52840755/parse-json-with-similar-elements-using-swiftyjson

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!