我有一個 JSON 回應(如下),我需要決議它 -
[
{
"id":123,
"name":"Fahim Rahman",
"age":25,
"friends":[
{
"firstName": "Imtiaz",
"lastName": "Khan",
"avatar_url": null
}
],
"groups":{
"xcet":{
"name":"xcek cert etsh tnhg",
"createdDate":"2022-10-31T10:00:48Z"
},
"juyt":{
"name":"jfd uyt you to",
"createdDate":"2021-09-13T10:00:00Z"
},
"some random key":{
"name": "some name",
"createdDate":"2026-03-27T10:00:00Z"
}
}
}
]
為了在我的代碼中決議這個,我創建了這個模型。我無法決議組,因為那不是串列而是物件-
import ObjectMapper
class Person: BaseObject {
@objc dynamic var ID: Int = -1
@objc dynamic var name: String = ""
@objc dynamic var age: Int = -1
var friendsList = List<Friends>()
override func mapping(map: ObjectMapper.Map) {
ID <- map["id"]
name <- map["name"]
age <- map["age"]
friendsList <- map["friends"]
}
}
class Friends: BaseObject {
@objc dynamic var firstName: String = ""
@objc dynamic var lastName: String = ""
@objc dynamic var avatarURL: String = ""
override func mapping(map: ObjectMapper.Map) {
firstName <- map["firstName"]
lastName <- map["name"]
avatarURL <- map["avatar_url"]
}
}
我知道這是一個糟糕的 JSON。這些組應該在串列而不是嵌套物件上,但不幸的是,我收到了這個回復。
這里在組的回應中,嵌套物件的數量是動態的,嵌套物件的鍵也是動態的。因此我無法將其決議為朋友屬性。
所以我的問題是,如何映射“組”?
uj5u.com熱心網友回復:
在映射組之前,我們需要一個可以將每個組與其鍵一起保存的類(即 xct)
例如
Class Groups: BaseObject {
@objc dynamic var key: String = ""
@objc dynamic var value: GroupsItem?
convenience init(key: String, value: GroupsItem) {
self.init()
self.key = key
self.value = value
}
}
Class GroupsItem: BaseObject {
@objc dynamic var name: String?
@objc dynamic var createdDate: String?
...
}
然后在您的 Person 類中,您可以將其映射為 -
private func mapGroupsItems(map: ObjectMapper.Map) -> List<GroupsItem> {
var rowsDictionary: [String: Groups]?
rowsDictionary <- map["groups"]
let rows = List<GroupsItem>()
if let dictionary = rowsDictionary {
for (key, value) in dictionary {
rows.append(GroupsItem(key: key, value: value))
}
}
return rows
}
不要忘記從映射中呼叫此方法 -
override public func mapping(map: ObjectMapper.Map) {
...
groups = mapGroupsItems(map: map)
}
uj5u.com熱心網友回復:
嘗試這種方法,使用自定義init(from decoder: Decoder)for Groups,對我來說效果很好。對非 SwiftUI 系統使用類似的方法。
struct ContentView: View {
@State var people: [Person] = []
var body: some View {
ForEach(people) { person in
Text(person.name)
ForEach(Array(person.groups.data.keys), id: \.self) { key in
Text(key).foregroundColor(.red)
Text(person.groups.data[key]?.name ?? "no name").foregroundColor(.blue)
Text(person.groups.data[key]?.createdDate ?? "no date").foregroundColor(.blue)
}
}
.onAppear {
let json = """
[
{
"id":123,
"name":"Fahim Rahman",
"age":25,
"friends":[
{
"firstName": "Imtiaz",
"lastName": "Khan",
"avatar_url": null
}
],
"groups":{
"xcet":{
"name":"xcek cert etsh tnhg",
"createdDate":"2022-10-31T10:00:48Z"
},
"juyt":{
"name":"jfd uyt you to",
"createdDate":"2021-09-13T10:00:00Z"
},
"some random key":{
"name": "some name",
"createdDate":"2026-03-27T10:00:00Z"
}
}
}
]
"""
if let data = json.data(using: .utf8) {
do {
self.people = try JSONDecoder().decode([Person].self, from: data)
print("---> people: \(people)")
} catch {
print("decode error: \(error)")
}
}
}
}
}
struct Person: Identifiable, Codable {
let id: Int
var name: String
var age: Int
var friends: [Friend]
var groups: Groups
}
struct Friend: Codable {
var firstName, lastName: String
var avatarURL: String?
enum CodingKeys: String, CodingKey {
case firstName, lastName
case avatarURL = "avatar_url"
}
}
struct Info: Codable {
var name: String
var createdDate: String
}
struct Groups: Identifiable, Codable {
let id = UUID()
var data: [String:Info] = [:]
init(from decoder: Decoder) throws {
do {
let container = try decoder.singleValueContainer()
self.data = try container.decode([String:Info].self)
} catch {
print(error)
}
}
}
uj5u.com熱心網友回復:
您的模型類結構將是
// MARK: - Welcome7Element
struct Welcome7Element {
let id: Int
let name: String
let age: Int
let friends: [Friend]
let groups: Groups
}
// MARK: - Friend
struct Friend {
let firstName, lastName: String
let avatarURL: NSNull
}
// MARK: - Groups
struct Groups {
let xcet, juyt, someRandomKey: Juyt
}
// MARK: - Juyt
struct Juyt {
let name: String
let createdDate: Date
}
uj5u.com熱心網友回復:
感謝@shakif_ 的富有洞察力的回答。這是我根據該答案解決此問題的方法-
import ObjectMapper
import RealmSwift
class Person: BaseObject {
@objc dynamic var ID: Int = -1
@objc dynamic var name: String = ""
@objc dynamic var age: Int = -1
var friendsList = List<Friends>()
var groups = List<Group>
override func mapping(map: ObjectMapper.Map) {
ID <- map["id"]
name <- map["name"]
age <- map["age"]
friendsList <- map["friends"]
groups = extractGroups(map)
}
private func extractGroups(_ map: ObjectMapper.Map) -> List<Group> {
let items = List<Group>()
var modifiedJSON = [String: Group]
modifiedJSON <- map["groups"]
for (key,value) in modifiedJSON {
let item = GroupMapper(key: key, value: value)
if let group = item.value {
items.append(group)
}
}
return items
}
}
class Friends: BaseObject {
@objc dynamic var firstName: String = ""
@objc dynamic var lastName: String = ""
@objc dynamic var avatarURL: String = ""
override func mapping(map: ObjectMapper.Map) {
firstName <- map["firstName"]
lastName <- map["name"]
avatarURL <- map["avatar_url"]
}
}
class Group: BaseObject {
@objc dynamic var name: String = ""
@objc dynamic var createdDate: String = ""
override func mapping(map: ObjectMapper.Map) {
name <- map["name"]
createdDate <- map["createdDate"]
}
}
struct GroupMapper {
var key: String = ""
var value: Group?
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/524514.html
