解析 Swift 中的动态可选键值 JSON
Parsing dynamic optional Key-Value JSON in Swift
如何解析动态键 (!papLZgcMalaVpYzStU:com.matrix.in":) 值或修改这两个结构以进行动态键处理
struct Join : Codable {
let papLZgcMalaVpYzStUcommatrixin : !papLZgcMalaVpYzStU:com.matrix.in?
enum CodingKeys: String, CodingKey {
case papLZgcMalaVpYzStUcommatrixin = "!papLZgcMalaVpYzStU:com.matrix.in"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
papLZgcMalaVpYzStUcommatrixin = !papLZgcMalaVpYzStU:com.matrix.in(from: decoder)
}
}
struct !papLZgcMalaVpYzStU:com.matrix.in : Codable {
let timeline : Timeline?
enum CodingKeys: String, CodingKey {
case timeline = "timeline"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
timeline = Timeline(from: decoder)
}
}
低于JSON.
{
"rooms": {
"join": {
"!papLZgcMalaVpYzStU:com.matrix.in": {
"timeline": {
"events": [{
"type": "m.room.message",
"sender": "@de1212138007:com.matrix.in",
"origin_server_ts": 1587395955315,
"content": {
"body": "thinks this is an example emote",
"msgtype": "m.emote"
},
"unsigned": {
"age": 7576335895
},
"event_id": "$$WLGTSEFSEF:localhost"
}, {
"type": "m.room.message",
"sender": "@de3212138007:com.matrix.in",
"origin_server_ts": 1587395955315,
"content": {
"body": "filename.jpg",
"info": {
"h": 398,
"mimetype": "image/jpeg",
"size": 31037,
"w": 394
},
"msgtype": "m.image",
"url": "mxc://localhost/JWEIFJgwEIhweiWJE"
},
"unsigned": {
"age": 7576335895
},
"event_id": "$$WLGTSEFSEF:localhost"
}, {
"type": "m.room.message",
"sender": "@de4212138007:com.matrix.in",
"origin_server_ts": 1587395955315,
"content": {
"body": "something-important.doc",
"filename": "something-important.doc",
"info": {
"mimetype": "application/msword",
"size": 46144
},
"msgtype": "m.file",
"url": "mxc://localhost/FHyPlCeYUSFFxlgbQYZmoEoe"
},
"unsigned": {
"age": 7576335895
},
"event_id": "$$WLGTSEFSEF:localhost"
}],
"prev_batch": "t16-12345_96395_1234_33138_4166_522_140_82600_1",
"limited": true
}
},
"!SecondRoomYzStU:com.matrix.in": {
"prev_batch": "t16-98262_96395_3402_33138_4166_522_140_82600_1",
"limited": true
}
}
}
}
我试过了
import Foundation
struct RootClass : Codable {
let rooms : Room?
enum CodingKeys: String, CodingKey {
case rooms = "rooms"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
rooms = try! Room(from: decoder)
}
}
struct Room : Codable {
let join : Join?
enum CodingKeys: String, CodingKey {
case join = "join"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
join = try! Join(from: decoder)
}
}
struct Join : Codable {
let papLZgcMalaVpYzStUcommatrixin : !papLZgcMalaVpYzStU:com.matrix.in?
enum CodingKeys: String, CodingKey {
case papLZgcMalaVpYzStUcommatrixin = "!papLZgcMalaVpYzStU:com.matrix.in"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
papLZgcMalaVpYzStUcommatrixin = !papLZgcMalaVpYzStU:com.matrix.in(from: decoder)
}
}
struct !papLZgcMalaVpYzStU:com.matrix.in : Codable {
let timeline : Timeline?
enum CodingKeys: String, CodingKey {
case timeline = "timeline"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
timeline = Timeline(from: decoder)
}
}
struct Timeline : Codable {
let events : [Event]?
let limited : Bool?
let prevBatch : String?
enum CodingKeys: String, CodingKey {
case events = "events"
case limited = "limited"
case prevBatch = "prev_batch"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
events = try values.decodeIfPresent([Event].self, forKey: .events)
limited = try values.decodeIfPresent(Bool.self, forKey: .limited)
prevBatch = try values.decodeIfPresent(String.self, forKey: .prevBatch)
}
}
struct Event : Codable {
let content : Content?
let eventId : String?
let originServerTs : Int?
let sender : String?
let type : String?
let unsigned : Unsigned?
enum CodingKeys: String, CodingKey {
case content = "content"
case eventId = "event_id"
case originServerTs = "origin_server_ts"
case sender = "sender"
case type = "type"
case unsigned = "unsigned"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
content = try! Content(from: decoder)
eventId = try values.decodeIfPresent(String.self, forKey: .eventId)
originServerTs = try values.decodeIfPresent(Int.self, forKey: .originServerTs)
sender = try values.decodeIfPresent(String.self, forKey: .sender)
type = try values.decodeIfPresent(String.self, forKey: .type)
unsigned = try! Unsigned(from: decoder)
}
}
struct Unsigned : Codable {
let age : Int?
enum CodingKeys: String, CodingKey {
case age = "age"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
age = try values.decodeIfPresent(Int.self, forKey: .age)
}
}
struct Content : Codable {
let body : String?
let info : Info?
let msgtype : String?
let url : String?
enum CodingKeys: String, CodingKey {
case body = "body"
case info = "info"
case msgtype = "msgtype"
case url = "url"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
body = try values.decodeIfPresent(String.self, forKey: .body)
info = try! Info(from: decoder)
msgtype = try values.decodeIfPresent(String.self, forKey: .msgtype)
url = try values.decodeIfPresent(String.self, forKey: .url)
}
}
struct Info : Codable {
let duration : Int?
let mimetype : String?
let size : Int?
enum CodingKeys: String, CodingKey {
case duration = "duration"
case mimetype = "mimetype"
case size = "size"
}
}
您在 JSON 中有两种类型的 key-value
。
已知 key
值
未知 key
值
你应该用已知结构解析 known Key-Value
s,用简单的 unknown Key-Value
s Dictionary
.
所以对于这个简单的 JSON:
{
"a":{
"RandomKey1":{
"a":"Some required value",
"b":"Some optional value here",
"c":12345
},
"RandomKey2":{
"a":"Another required value"
}
}
}
结构将是:
struct KnownTypeRandom: Codable {
let a: String
let b: String?
let c: Int?
}
struct KnownTypeA: Codable {
let a: [String: KnownTypeRandom]
}
然后您可以通过枚举未知键来找到未知键,例如:
for unknown in knownObjectA.a {
print(unknown.key)
}
这将打印出:
RandomKey1
RandomKey2
如何解析动态键 (!papLZgcMalaVpYzStU:com.matrix.in":) 值或修改这两个结构以进行动态键处理
struct Join : Codable {
let papLZgcMalaVpYzStUcommatrixin : !papLZgcMalaVpYzStU:com.matrix.in?
enum CodingKeys: String, CodingKey {
case papLZgcMalaVpYzStUcommatrixin = "!papLZgcMalaVpYzStU:com.matrix.in"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
papLZgcMalaVpYzStUcommatrixin = !papLZgcMalaVpYzStU:com.matrix.in(from: decoder)
}
}
struct !papLZgcMalaVpYzStU:com.matrix.in : Codable {
let timeline : Timeline?
enum CodingKeys: String, CodingKey {
case timeline = "timeline"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
timeline = Timeline(from: decoder)
}
}
低于JSON.
{
"rooms": {
"join": {
"!papLZgcMalaVpYzStU:com.matrix.in": {
"timeline": {
"events": [{
"type": "m.room.message",
"sender": "@de1212138007:com.matrix.in",
"origin_server_ts": 1587395955315,
"content": {
"body": "thinks this is an example emote",
"msgtype": "m.emote"
},
"unsigned": {
"age": 7576335895
},
"event_id": "$$WLGTSEFSEF:localhost"
}, {
"type": "m.room.message",
"sender": "@de3212138007:com.matrix.in",
"origin_server_ts": 1587395955315,
"content": {
"body": "filename.jpg",
"info": {
"h": 398,
"mimetype": "image/jpeg",
"size": 31037,
"w": 394
},
"msgtype": "m.image",
"url": "mxc://localhost/JWEIFJgwEIhweiWJE"
},
"unsigned": {
"age": 7576335895
},
"event_id": "$$WLGTSEFSEF:localhost"
}, {
"type": "m.room.message",
"sender": "@de4212138007:com.matrix.in",
"origin_server_ts": 1587395955315,
"content": {
"body": "something-important.doc",
"filename": "something-important.doc",
"info": {
"mimetype": "application/msword",
"size": 46144
},
"msgtype": "m.file",
"url": "mxc://localhost/FHyPlCeYUSFFxlgbQYZmoEoe"
},
"unsigned": {
"age": 7576335895
},
"event_id": "$$WLGTSEFSEF:localhost"
}],
"prev_batch": "t16-12345_96395_1234_33138_4166_522_140_82600_1",
"limited": true
}
},
"!SecondRoomYzStU:com.matrix.in": {
"prev_batch": "t16-98262_96395_3402_33138_4166_522_140_82600_1",
"limited": true
}
}
}
}
我试过了
import Foundation
struct RootClass : Codable {
let rooms : Room?
enum CodingKeys: String, CodingKey {
case rooms = "rooms"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
rooms = try! Room(from: decoder)
}
}
struct Room : Codable {
let join : Join?
enum CodingKeys: String, CodingKey {
case join = "join"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
join = try! Join(from: decoder)
}
}
struct Join : Codable {
let papLZgcMalaVpYzStUcommatrixin : !papLZgcMalaVpYzStU:com.matrix.in?
enum CodingKeys: String, CodingKey {
case papLZgcMalaVpYzStUcommatrixin = "!papLZgcMalaVpYzStU:com.matrix.in"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
papLZgcMalaVpYzStUcommatrixin = !papLZgcMalaVpYzStU:com.matrix.in(from: decoder)
}
}
struct !papLZgcMalaVpYzStU:com.matrix.in : Codable {
let timeline : Timeline?
enum CodingKeys: String, CodingKey {
case timeline = "timeline"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
timeline = Timeline(from: decoder)
}
}
struct Timeline : Codable {
let events : [Event]?
let limited : Bool?
let prevBatch : String?
enum CodingKeys: String, CodingKey {
case events = "events"
case limited = "limited"
case prevBatch = "prev_batch"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
events = try values.decodeIfPresent([Event].self, forKey: .events)
limited = try values.decodeIfPresent(Bool.self, forKey: .limited)
prevBatch = try values.decodeIfPresent(String.self, forKey: .prevBatch)
}
}
struct Event : Codable {
let content : Content?
let eventId : String?
let originServerTs : Int?
let sender : String?
let type : String?
let unsigned : Unsigned?
enum CodingKeys: String, CodingKey {
case content = "content"
case eventId = "event_id"
case originServerTs = "origin_server_ts"
case sender = "sender"
case type = "type"
case unsigned = "unsigned"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
content = try! Content(from: decoder)
eventId = try values.decodeIfPresent(String.self, forKey: .eventId)
originServerTs = try values.decodeIfPresent(Int.self, forKey: .originServerTs)
sender = try values.decodeIfPresent(String.self, forKey: .sender)
type = try values.decodeIfPresent(String.self, forKey: .type)
unsigned = try! Unsigned(from: decoder)
}
}
struct Unsigned : Codable {
let age : Int?
enum CodingKeys: String, CodingKey {
case age = "age"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
age = try values.decodeIfPresent(Int.self, forKey: .age)
}
}
struct Content : Codable {
let body : String?
let info : Info?
let msgtype : String?
let url : String?
enum CodingKeys: String, CodingKey {
case body = "body"
case info = "info"
case msgtype = "msgtype"
case url = "url"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
body = try values.decodeIfPresent(String.self, forKey: .body)
info = try! Info(from: decoder)
msgtype = try values.decodeIfPresent(String.self, forKey: .msgtype)
url = try values.decodeIfPresent(String.self, forKey: .url)
}
}
struct Info : Codable {
let duration : Int?
let mimetype : String?
let size : Int?
enum CodingKeys: String, CodingKey {
case duration = "duration"
case mimetype = "mimetype"
case size = "size"
}
}
您在 JSON 中有两种类型的 key-value
。
已知
key
值未知
key
值
你应该用已知结构解析 known Key-Value
s,用简单的 unknown Key-Value
s Dictionary
.
所以对于这个简单的 JSON:
{
"a":{
"RandomKey1":{
"a":"Some required value",
"b":"Some optional value here",
"c":12345
},
"RandomKey2":{
"a":"Another required value"
}
}
}
结构将是:
struct KnownTypeRandom: Codable {
let a: String
let b: String?
let c: Int?
}
struct KnownTypeA: Codable {
let a: [String: KnownTypeRandom]
}
然后您可以通过枚举未知键来找到未知键,例如:
for unknown in knownObjectA.a {
print(unknown.key)
}
这将打印出:
RandomKey1
RandomKey2