如何在Swift中将JSON解析为嵌套结构?

时间:2018-10-04 16:24:18

标签: json swift codable

我将解析此JSON:

{
    "status": 1,
    "member": {
        "id": "3",
        "member_no": "1111",
        "username": "uname",
        "name": "name",
        "email": "user@name.com",
        "phone": "123 123",
        "point": "100",
        "expiry": "2019-09-22",
        "grade": {
            "id": "2",
            "name": "Member"
        }
    }
}

我创建了这个结构:

struct User: Codable {
    var status: Int?
    var member: Member?
    var msg: String?

    struct Member: Codable {
        var id: Int?
        var member_no: String?
        var username: String?
        var name: String?
        var email: String?
        var phone: String?
        var point: String?
        var expiry: String?
        var grade: Grade?

        struct Grade: Codable {
            var id: Int?
            var name: String?
        }
    }
}

并使用它来解码:

let decoder = JSONDecoder()
let user = try decoder.decode(User.self, from: data)

但是我得到了这个错误:

  

由于数据格式不正确,因此无法读取。

如果结构只有一个级别,那就没问题:

struct User: Codable {
    var status: Int?
    var msg: String?
}

如何编写一个结构以匹配此JSON?

5 个答案:

答案 0 :(得分:0)

您可能想尝试以下方法,这对我来说似乎很好。

首先,我们需要为结构CodingKeys创建User

使用可编码时,即使成员内部的MemberGrade彼此嵌套。您应该从用户结构中声明那些结构。

如以下所示,成员和等级应符合Codable,而用户扩展名应符合Decodable,并通过将其用作容器使用解码器进行初始化。

此外,由于在您的json文件中,用户和等级中的id都为String,但是在您的代码中,您将它们声明为Int,所以我也对其进行了修复。

下面的代码实现了我上面提到的structs和CodingKeys,尝试按照我的方式进行处理,或者通过复制粘贴来进行尝试,应该没事:

具有CodingKeys的用户结构:

struct User {
var status: Int?
var member: Member?

enum CodingKeys: String, CodingKey {
    case status = "status"
    case member = "member"
}
}

成员和等级结构:

struct Member: Codable {
var id: String?
var member_no: String?
var username: String?
var name: String?
var email: String?
var phone: String?
var point: String?
var expiry: String?
var grade: Grade?
}

struct Grade: Codable {
var id: String?
var name: String?
}

用户符合编码要求的扩展名:

extension User: Decodable {
init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)

    self.status = try container.decode(Int?.self, forKey: .status)
    self.member = try container.decode(Member?.self, forKey: .member)
}
}

现在创建一个解码器,并尝试按以下方式对其进行解码:

    let decoder = JSONDecoder()
    let user = try! decoder.decode(User.self, from: data)

我希望这对您有帮助并能正常工作

答案 1 :(得分:0)

xcode可能会向您抛出一个错误,说您的结构不符合可解码协议,您对此并不关心:]

这是您的结构(模型)的外观


struct User: Codable {
    let status: Int?
    let member: Member?
}

struct Member: Codable { let id, memberNo, username, name: String? let email, phone, point, expiry: String? let grade: Grade?

enum CodingKeys: String, CodingKey {
    case id
    case memberNo = "member_no"
    case username, name, email, phone, point, expiry, grade
}

}

struct Grade: Codable { let id, name: String? }

答案 2 :(得分:0)

试试这个

import Foundation

struct User: Codable {
    let status: Int
    let member: Member
}

struct Member: Codable {
    let id, memberNo, username, name: String
    let email, phone, point, expiry: String
    let grade: Grade

    enum CodingKeys: String, CodingKey {
        case id
        case memberNo = "member_no"
        case username, name, email, phone, point, expiry, grade
    }
}

struct Grade: Codable {
    let id, name: String
}

答案 3 :(得分:-1)

您的ID中包含字符串,而不是整数:

struct User: Codable {
    var status: Int?
    var member: Member?

    struct Member: Codable {
        var id: String?
        var member_no: String?
        var username: String?
        var name: String?
        var email: String?
        var phone: String?
        var point: String?
        var expiry: String?
        var grade: Grade?

        struct Grade: Codable {
            var id: String?
            var name: String?
        }
    }
}

let decoder = JSONDecoder()
do {
    let user = try decoder.decode(User.self, from: data)
} catch {
    print(error)
}

答案 4 :(得分:-1)

结构用户:可编码{ 无功状态:Int? var 成员:成员? var msg: 字符串?

struct Member: Codable {
    var id: String?
    var member_no: String?
    var username: String?
    var name: String?
    var email: String?
    var phone: String?
    var point: String?
    var expiry: String?
    var grade: Grade?

    struct Grade: Codable {
        var id: String?
        var name: String?
    }
}

}