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 ?
答案 0 :(得分:2)
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 }