本文介绍了Swift Json将嵌套数组/字典解码为平面模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在Swift中将以下json对象解码为我的 User 模型.

I am trying to decode the following json object to my User model in Swift.

我的问题是从 tokens 数组中解码出值 _id token ,其中数组中的第一个令牌包含值I想要解码为User.tokenId和User.token.

My issue is decoding the values _id and token out of the tokens array, where the first token in the array contains the values I want to decode into User.tokenId and User.token.

我试图将值直接提取/映射到我的User模型结构中,而在我的User模型中没有其他嵌套结构(例如 struct Token {var id:String,var token:String} )

I am trying to extract/map the values directly into my User model struct without having another nested struct in my User model ( such as struct Token { var id: String , var token: String } )

let json = """
    {
        "currentLocation": {
            "latitude": 0,
            "longitude": 0
        },
        "profileImageUrl": "",
        "bio": "",
        "_id": "601453e4aae564fc19075b68",
        "username": "johnsmith",
        "name": "john",
        "email": "johnsmith@gmail.com",
        "keywords": ["word", "weds"],
        "tokens": [
            {
                "_id": "213453e4aae564fcqu775b69",
                "token": "eyJhbGciOiJIUzqoNiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MDE0NTNlNGFhZTU2NGZjMTkwNzViNjgiLCJpYXQiOjE2MTE5NDQ5MzIsImV4cCI6MTYxMjM3NjkzMn0.PbTsA3B0MAfcVvEF1UAMhUXFiqIL1FcxVFGgMTZ5HCk"
            }
        ],
        "createdAt": "2021-01-29T18:28:52.845Z",
        "updatedAt": "2021-01-29T18:28:52.883Z"
    }
    """.data(using: .utf8)!


struct User: Codable {
    var latitude: Double
    var longitude: Double
    var profileImageUrl: String
    var bio: String
    var userId: String
    var username: String
    var name: String
    var email: String
    var keywords: [String]
    var tokenId: String
    var token: String
    var createdAt: Date
    var updatedAt: Date

    private enum UserKeys: String, CodingKey {
        case currentLocation
        case profileImageUrl
        case bio
        case userId = "_id"
        case username
        case name
        case email
        case keywords
        case tokens
        case createdAt
        case updatedAt
    }

    private enum CurrentLocationKeys: String, CodingKey {
        case latitude
        case longitude
    }

    private enum TokenKeys: String, CodingKey {
        case tokenId = "_id"
        case token
    }

    init(from decoder: Decoder) throws {

        let userContainer = try decoder.container(keyedBy: UserKeys.self)
              let currentLocationContainer = try userContainer.nestedContainer(keyedBy: CurrentLocationKeys.self, forKey: .currentLocation)
              self.latitude = try currentLocationContainer.decode(Double.self, forKey: .latitude)
              self.longitude = try currentLocationContainer.decode(Double.self, forKey: .longitude)
            self.profileImageUrl = try userContainer.decode(String.self, forKey: .profileImageUrl)
            self.bio = try userContainer.decode(String.self, forKey: .bio)
            self.userId = try userContainer.decode(String.self, forKey: .userId)
            self.username = try userContainer.decode(String.self, forKey: .username)
            self.name = try userContainer.decode(String.self, forKey: .name)
            self.email = try userContainer.decode(String.self, forKey: .email)
            self.keywords = try userContainer.decode([String].self, forKey: .keywords)
              let tokensContainer = try userContainer.nestedContainer(keyedBy: TokenKeys.self, forKey: .tokens)
              self.tokenId = try tokensContainer.decode(String.self, forKey: .tokenId)
              self.token = try tokensContainer.decode(String.self, forKey: .token)
            self.createdAt = try userContainer.decode(Date.self, forKey: .createdAt)
            self.updatedAt = try userContainer.decode(Date.self, forKey: .updatedAt)
    }
}

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

推荐答案

首先,我认为您的 decoder 具有适当的日期解码策略,能够将ISO8601字符串解码为日期.

First of all I assume that your decoder has an appropriate date decoding strategy to be able to decode the ISO8601 strings to Date.

token 词典的封闭容器是一个数组.您必须插入一个中间 nestedUnkeyedContainer

The enclosing container of the token dictionary is an array. You have to insert an intermediate nestedUnkeyedContainer

...
var arrayContainer = try userContainer.nestedUnkeyedContainer(forKey: .tokens)
let tokensContainer = try arrayContainer.nestedContainer(keyedBy: TokenKeys.self)
self.tokenId = try tokensContainer.decode(String.self, forKey: .tokenId)
self.token = try tokensContainer.decode(String.self, forKey: .token)
...

将JSON解码为多种结构的代码要少得多

It's much less code to decode the JSON into multiple structs

这篇关于Swift Json将嵌套数组/字典解码为平面模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-20 18:00
查看更多