我刚刚学习了Argo基础知识,并且能够解码99%的JSON。现在我面临以下结构(像“5447”和“5954”这样的键是动态的)并需要帮助:
{
"5447": {
"business_id": 5447,
"rating": 5,
"comment": "abcd",
"replies_count": 0,
"message_id": 2517
},
"5954": {
"business_id": 5954,
"rating": 3,
"comment": "efgh",
"replies_count": 0,
"message_id": 633
}
}
Argo解码的典型示例如下:
struct User {
let id: Int
let name: String
}
用于JSON结构(键是固定的“id”和“name”):
{
"id": 124,
"name": "someone"
}
使用类似的东西:
extension User: Decodable {
static func decode(j: JSON) -> Decoded<User> {
return curry(User.init)
<^> j <| "id"
<*> j <| "name"
}
}
但是我需要解析的数据结构不适合这个例子。
更新:使用Tony的第一个实现,在最后一行进行了一些小修改,我完成了我的工作。这是完整的工作代码:
Business.swift :
import Argo
import Curry
import Runes
struct Business {
let businessID: Int
let rating: Double?
let comment: String?
let repliesCount: Int?
let messageID: Int?
}
extension Business: Decodable {
static func decode(_ json: JSON) -> Decoded<Business> {
let c0 = curry(Business.init)
<^> json <| "business_id"
<*> json <|? "rating"
return c0
<*> json <|? "comment"
<*> json <|? "replies_count"
<*> json <|? "message_id"
}
}
Businesses.swift
import Argo
import Runes
struct Businesses {
let businesses: [Business]
}
extension Businesses: Decodable {
static func decode(_ json: JSON) -> Decoded<Businesses> {
let dict = [String: JSON].decode(json)
let arr = dict.map { Array($0.map { $1 }) }
let jsonArr = arr.map { JSON.array($0) }
return Businesses.init <^> jsonArr.map([Business].decode).value ?? .success([])
}
}
答案 0 :(得分:4)
如果字典中的键是动态的,那么您必须走出Argo提供的便捷操作符。您首先需要获取JSON
对象元素,然后自己映射它。由于密钥在这里是无关紧要的(因为id也在嵌入式字典中),它实际上不会太糟糕。最简单的方法是创建一个新结构来包装它:
struct Businesses: Decodable {
let businesses: [Business]
static func decode(_ json: JSON) -> Decoded<Businesses> {
// Get dictionary
let dict: Decoded<[String: JSON]> = [String: JSON].decode(json)
// Transform dictionary to array
let array: Decoded<[JSON]> = dict.map { Array($0.map { $1 }) }
// Wrap array back into a JSON type
let jsonArray: Decoded<JSON> = array.map { JSON.array($0) }
// Decode the JSON type like we would with no key
return Businesses.init <^> array.map([Business].decode)
}
}
我们在这里做的是获取字典并将其转换为数组,以便我们可以像任何其他数组一样对其进行解码。
你也可以跳过转换到数组部分并从字典中解码它,如下所示:
static func decode(_ json: JSON) -> Decoded<Businesses> {
// Get dictionary
let dict: Decoded<[String: JSON]> = [String: JSON].decode(json)
// Map over the dictionary and decode the values
let result: Decoded<[Businesses]> = dict.flatMap { object in
let decoded: [Decoded<Business>] = Array(object.map { decode($1) })
return sequence(decoded)
}
return Businesses.init <^> result
}
我没有尝试任何此类代码,因此可能会有一些调整。此外,您可能不需要所有类型注释,但我添加它们以帮助解释代码。您也可以在新结构模型之外使用此代码,具体取决于您的应用程序。