3

I have the following response from an API:

[
    {
        "stores": [
            {
                "store": {
                    "Name": "A store name",
                    "City": "NY"
                }
            },
            {
                "store": {
                    "Name": "A second store name",
                    "City": "ny2"
                }
            }
        ]
    }, 

    {

        "products": [
            {
                "product": {
                    "name": "a product",
                    "price": "1"
                }
            },
            {
                "product": {
                    "name": "a second product",
                    "price": "2"
                }
            }
        ]

    }

]

For the two JSON objects (stores and products) I've created the following structures:

struct shops_response: Codable {

    var stores: [stores]
}

struct products_response: Codable {

    var products: [products]
}


struct stores: Codable {
    var store: store
}

struct store: Codable {
    var Name:String
    var City:String
}

struct products: Codable {
    var product: product
}

struct product: Codable {

    var name:String
    var price:String

}

Using this code from below I've successfully parsed the response (where APIresponse.json is the json received from the API - I'm using it for testing purposes only):

let path = Bundle.main.path(forResource: "APIresponse", ofType: "json")
let url = URL(fileURLWithPath: path!)

let data = try! Data(contentsOf:url)

let jsonArray = try! JSONSerialization.jsonObject(with: data, options: []) as? [[String:Any]]
let storesJsonData = try! JSONSerialization.data(withJSONObject: jsonArray![0], options: .prettyPrinted)
let productsJsonData = try! JSONSerialization.data(withJSONObject: jsonArray![1], options: .prettyPrinted)


let stores = try! JSONDecoder().decode(shops_response.self, from: storesJsonData)
let products = try! JSONDecoder().decode(products_response.self, from: productsJsonData)

My question is: Is there another cleaner/easier way to parse this type of json in Swift 4 ?

3
  • 1
    That's a very inconvenient JSON. Are you responsible for it? An array stores containing dictionaries each containing only one(!) dictionary with key store is cumbersome and actually redundant. Commented Feb 3, 2018 at 10:43
  • @vadian No... It's a JSON response from an API that I have to work with. Indeed the JSON it's quite difficult. The only solution that I've found is the one I've presented in the question. Commented Feb 3, 2018 at 10:49
  • I'd ask the owner of the service to consider sending a more suitable format. 😉 Commented Feb 3, 2018 at 10:51

1 Answer 1

6

This is really an awkwardly structured JSON. If you can't get the sender to change the format, here's my attempt at parsing it using JSONDecoder:

typealias Response = [Entry]

struct Entry: Codable {
    let stores: [StoreEntry]?
    let products: [ProductEntry]?
}

struct ProductEntry: Codable {
    let product: Product
}

struct Product: Codable {
    let name, price: String
}

struct StoreEntry: Codable {
    let store: Store
}

struct Store: Codable {
    let name, city: String

    enum CodingKeys: String, CodingKey {
        case name = "Name"
        case city = "City"
    }
}

let response = try JSONDecoder().decode(Response.self, from: data)
let stores = response.flatMap { $0.stores.map { $0.map { $0.store } } }.flatMap { $0 }
let products = response.flatMap { $0.products.map { $0.map { $0.product } } }.flatMap { $0 }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.