[英]How to Decode Nested dictionary with nested arrays using Swift Decodable property?
The actual JSON,that I need to parse in swift4 is, 我需要在swift4中解析的实际JSON是,
{
"class": {
"semester1": [
{
"name": "Kal"
},
{
"name": "Jack"
},
{
"name": "Igor"
}
],
"subjects": [
"English",
"Maths"
]
},
"location": {
"Dept": [
"EnglishDept",
],
"BlockNo": 1000
},
"statusTracker": {
"googleFormsURL": "beacon.datazoom.io",
"totalCount": 3000
}
}
The code that I'd tried but failed to execute is, 我尝试过但执行失败的代码是
struct Class: Decodable {
let semester: [internalComponents]
let location: [location]
let statusTracker: [statusTracker]
enum CodingKeys: String, CodingKey {
case semester = "semester1"
case location = "location"
case statusTracker = "statusTracker"
}
}
struct location: Decodable {
let Dept: [typesSubIn]
let BlockNo: Int
}
struct statusTracker: Decodable {
let googleFormsURL: URL
let totalCount: Int
}
struct internalComponents: Decodable {
let semester1: [semsIn]
let subjects: [subjectsIn]
}
struct semsIn: Decodable {
let nameIn: String
}
struct subjectsIn: Decodable {
let subjects: String
}
struct Dept: Decodable {
let Depts: String
}
I know it's completely wrong can someone give the actual format? 我知道有人可以提供实际格式是完全错误的吗? I'm actually confused with the format for "subjects".It's not compiling as a whole too.
我实际上对“主题”的格式感到困惑。它也不是整体编译的。
There are many issues. 有很多问题。
You are making a common mistake by ignoring the root object partially. 通过部分忽略根对象,您经常犯错误。
Please take a look at the JSON: On the top level there are 3 keys class
, location
and statusTracker
. 请看一下JSON:在顶层,有3个键
class
, location
和statusTracker
。 The values for all 3 keys are dictionaries, there are no arrays. 所有3个键的值都是字典,没有数组。
Since class
(lowercase) is a reserved word, I'm using components
. 由于
class
(小写)是保留字,因此我正在使用components
。 By the way please conform to the naming convention that struct names start with a capital letter. 顺便说一句,请遵循结构名称以大写字母开头的命名约定。
struct Root : Decodable {
let components : Class
let location: Location
let statusTracker: StatusTracker
enum CodingKeys: String, CodingKey { case components = "class", location, statusTracker }
}
There are many other problems. 还有许多其他问题。 Here a consolidated version of the other structs
这里是其他结构的合并版本
struct Class: Decodable {
let semester1: [SemsIn]
let subjects : [String]
}
struct Location: Decodable {
let dept : [String]
let blockNo : Int
enum CodingKeys: String, CodingKey { case dept = "Dept", blockNo = "BlockNo" }
}
struct SemsIn: Decodable {
let name: String
}
struct StatusTracker: Decodable {
let googleFormsURL: String // URL is no benefit
let totalCount: Int
}
Now decode Root
现在解码
Root
do {
let result = try decoder.decode(Root.self, from: data)
} catch { print(error) }
It looks like you sterilize Class
object in wrong way. 看起来您以错误的方式对
Class
对象进行了消毒。 It should looks like: 它看起来应该像这样:
struct Class: Decodable {
let class: [internalComponents]
let location: [location]
let statusTracker: [statusTracker]
}
There are a few things here causing your issue. 这里有几件事引起您的问题。
Try this code from my playground: 在我的游乐场尝试以下代码:
let jsonData = """
{
"class": {
"semester1": [{
"name": "Kal"
}, {
"name": "Jack"
}, {
"name": "Igor"
}],
"subjects": [
"English",
"Maths"
]
},
"location": {
"Dept": [
"EnglishDept"
],
"BlockNo": 1000
},
"statusTracker": {
"googleFormsURL": "beacon.datazoom.io",
"totalCount": 3000
}
}
""".data(using: .utf8)!
struct Response: Decodable {
let cls: Class
let location: Location
let statusTracker: statusTracker
enum CodingKeys: String, CodingKey {
case cls = "class"
case location
case statusTracker
}
}
struct Class: Decodable {
let semester: [SemesterStudents]
let subjects: [String]
enum CodingKeys: String, CodingKey {
case semester = "semester1"
case subjects
}
}
struct Location: Decodable {
let dept: [String]
let blockNo: Int
enum CodingKeys: String, CodingKey {
case dept = "Dept"
case blockNo = "BlockNo"
}
}
struct statusTracker: Decodable {
let googleFormsURL: URL
let totalCount: Int
}
struct SemesterStudents: Decodable {
let name: String
}
struct Dept: Decodable {
let Depts: String
}
do {
let result = try JSONDecoder().decode(Response.self, from: jsonData)
print(result)
} catch let error {
print(error)
}
Another approach is to create an intermediate model that closely matches the JSON, let Swift generate the methods to decode it, and then pick off the pieces that you want in your final data model: 另一种方法是创建一个与JSON紧密匹配的中间模型,让Swift生成对它进行解码的方法,然后从最终数据模型中挑选出所需的片段:
// snake_case to match the JSON
fileprivate struct RawServerResponse: Decodable {
struct User: Decodable {
var user_name: String
var real_info: UserRealInfo
}
struct UserRealInfo: Decodable {
var full_name: String
}
struct Review: Decodable {
var count: Int
}
var id: Int
var user: User
var reviews_count: [Review]
}
struct ServerResponse: Decodable {
var id: String
var username: String
var fullName: String
var reviewCount: Int
init(from decoder: Decoder) throws {
let rawResponse = try RawServerResponse(from: decoder)
// Now you can pick items that are important to your data model,
// conveniently decoded into a Swift structure
id = String(rawResponse.id)
username = rawResponse.user.user_name
fullName = rawResponse.user.real_info.full_name
reviewCount = rawResponse.reviews_count.first!.count
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.