ios - 在 Swift 中解析动态可选键值 JSON

标签 ios json xcode swift4 swift5

如何解析动态 key ( !papLZgcMalaVpYzStU:com.matrix.in": )值或修改这两个结构以进行动态 key 处理

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"
    }
}

最佳答案

您有两种类型的 key-value JSON 中的 s。

  • 已知key值(value)观
  • 未知key值(value)观

  • 你应该解析 已知 Key-Value具有已知结构的 s 和 未知 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
    

    关于ios - 在 Swift 中解析动态可选键值 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62949292/

    相关文章:

    ios - iOS 上的 sqlite3 中的 "No such function: REGEXP"

    ios - swift : Cannot convert value of type '()' to expected argument type '[Double]'

    iphone - 渐变背景 UIScrollView

    java - 尝试通过 Spring Boot Rest 使用 Jackson 验证 JSON

    sql - Oracle - 在单个 SQL 查询中解析多个 JSON 值

    ios - NSNumber 在 Objective-C 中存储 NSDictionary 的对象

    c - 如何在 Mac 上使用 C I/O 重定向?

    ios - ld : truncated fat file

    javascript - Jquery .change 函数无法通过 javascript 工作

    xcode - 模拟指标 "Orientation"下拉列表缺失