我在使用 swift4 中的 Codable 序列化复杂的嵌套 json 时遇到困难。

I am having difficulty using the Codable in swift4 to serialize a complex nested json.

我正在使用 alamofire 和 swiftyjson 检索本地商店的折扣数据。我在尝试使用 codable 序列化以下 json 并调用集合视图控制器中的元素时遇到了很多麻烦。我是 swift 的新手,但不熟悉网络,因此非常感谢具有更多专业知识的人提供的任何帮助。

谢谢!!!

{
"query": {
    "total": 517,
    "page": 1,
    "per_page": 20,
    "query": null,
    "location": {
        "latitude": 39.9592472,
        "longitude": -75.16149250000001
    },
    "radius": 10,
    "online": null,
    "category_slugs": null,
    "provider_slugs": null,
    "updated_after": null,
    "order": "distance"
},
"deals": [
    {
        "deal": {
            "id": 14302,
            "title": "Chimney and Fireplace Cleaning with Safety Inspection from Samuel Duct And Dryer Cleaning (Up to 88% Off)",
            "short_title": "Up to 88% Off Services from Samuel Duct And Dryer Cleaning",
            "description": "Choice of: Chimney and Fireplace Sweeping for Chimneys of Up to 10 Feet. Includes: Sweeping and cleaning of chimneys of up to 10 feet Sweeping and cleaning of fireplace Chimney and fireplace inspection",
            "fine_print": "May be repurchased every 90 days. Appointment required. Limit 2 per person, may buy 2 additional as gifts. Valid only for option purchased. Additional fee may be required for certain chimney/fireplace types. Valid in New Jersey, Philadelphia and Delaware, 95 miles from zip code 08550.",
            "number_sold": 0,
            "url": "https://api.discountapi.com/v2/deals/14302/click?api_key=hvdhgCzK",
            "price": 49,
            "value": 249.99,
            "discount_amount": 200.99,
            "discount_percentage": 0.8039921596863875,
            "provider_name": "Groupon",
            "provider_slug": "groupon",
            "category_name": "Home Services",
            "category_slug": "home-services",
            "image_url": "https://api.discountapi.com/v2/deals/14302/image?api_key=hvdhgCzK",
            "online": false,
            "expires_at": "2018-08-15T00:00:00Z",
            "created_at": "2018-02-16T13:46:43Z",
            "updated_at": "2018-04-15T11:22:15Z",
            "merchant": {
                "id": 10681,
                "name": "Samuel Duct And Dryer Cleaning",
                "address": "N 13th St & Vine St",
                "locality": "Philadelphia",
                "region": "PA",
                "postal_code": "19107",
                "country": "US",
                "latitude": 39.9573863,
                "longitude": -75.1603041,
                "url": "http://www.facebook.com/samuelductndryercleaning"
            }
        }
    },
    {
        "deal": {
            "id": 405186,
            "title": "Fine Palate",
            "short_title": "Fine Palate",
            "description": "Bring your family in, take a seat and let us do all the work. We have a staff of trained professionals and will do everything in your power to make your dining experience one to remember.",
            "fine_print": "Minimum purchase of  at restaurant, Mon-Thurs. Minimum purchase of  on Fri-Sun. Purchase must include food. Not valid for alcohol. Not valid for Happy Hour.",
            "url": "https://api.discountapi.com/v2/deals/405186/click?api_key=hvdhgCzK",
            "price": 10,
            "value": 25,
            "discount_amount": 15,
            "discount_percentage": 0.6,
            "provider_name": "Restaurant.com",
            "provider_slug": "restaurant-com",
            "category_name": "Restaurants",
            "category_slug": "restaurants",
            "image_url": "https://api.discountapi.com/v2/deals/405186/image?api_key=hvdhgCzK",
            "online": false,
            "created_at": "2018-03-20T20:08:24Z",
            "updated_at": "2018-04-14T14:08:46Z",
            "merchant": {
                "id": 194475,
                "name": "Fine Palate",
                "address": "",
                "region": "",
                "country": "US",
                "latitude": 39.957133,
                "longitude": -75.164206
            }
        }
    }

]

}

这是一个起点。每个字典({})都在自定义结构中解码,键是结构成员。 []表示一个数组。

deals的结构非常愚蠢不好,deal字典实际上是多余的,需要一个自定义的初始化器来将字典转换成一个大批。

如果您负责 JSON 更改它并发送一个简单的字典数组。

日期解码策略 .iso8601 将 ISO8601 字符串转换为 Date 个实例。
密钥解码策略 convertFromSnakeCasesnake_cased 密钥转换为 camelCased 属性。
URL 字符串被解码为 URL

struct Root : Decodable {
    let query : Query
    let deals : [Deal]

    private enum  CodingKeys: String, CodingKey { case query, deals }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        query = try container.decode(Query.self, forKey: .query)
        let dealData = try container.decode([[String:Deal]].self, forKey: .deals)
        deals = dealData.map { [=10=]["deal"]! }
    }
}

struct Query : Decodable {
    let total : Int
    let page : Int
    let perPage : Int
    let location : Location
}

struct Location : Decodable {
    let latitude, longitude : Double
}

struct Deal : Decodable {
    let id : Int
    let url : URL
    let createdAt : Date
    let expiresAt : Date?
}

data假设为JSON

的UTF8编码数据
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
decoder.keyDecodingStrategy = .convertFromSnakeCase
let result = try decoder.decode(Root.self, from: data)
print(result)