1

how to parse dynamic key (!papLZgcMalaVpYzStU:com.matrix.in":)value or modified these two struct for dynamic key handling

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

}

for below 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
        }
    }
}

}

I have tried

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"
    }
}
3
  • thanks but I basically want to know how to get all Dynamic key to be parse Commented Jul 18, 2020 at 13:26
  • Quite simply to decode a dictionary [String:Something] and enumerate the keys. Commented Jul 18, 2020 at 13:28
  • please check now I have optimise the code unable to get all keys value !papLZgcMalaVpYzStU:com.matrix.in of rooms etc Commented Jul 18, 2020 at 15:56

1 Answer 1

2
+100

You have tow types of key-values in the JSON.

  1. Known key values

  2. Unknown key values

You should parse known Key-Values with known structs, and unknown Key-Values with a simple Dictionary.

So for this simplyfied JSON:

{
   "a":{
      "RandomKey1":{
         "a":"Some required value",
         "b":"Some optional value here",
         "c":12345
      },
      "RandomKey2":{
         "a":"Another required value"
      }
   }
}

Structs would be:

struct KnownTypeRandom: Codable {
    let a: String
    let b: String?
    let c: Int?
}

struct KnownTypeA: Codable {
    let a: [String: KnownTypeRandom]
}

Then you can find unknown keys by enumerating over unknown keys like:

for unknown in knownObjectA.a {
    print(unknown.key)
}

This will print out:

RandomKey1
RandomKey2
Sign up to request clarification or add additional context in comments.

5 Comments

Feel free to ask any further questions.
what if there is another array of dictionary inside RandomKey1 RandomKey2 etc ? with optional values ? can you help me out in that ? so I will accept this answer
So there will be another known or unknown state. Then you can retry the steps. For Optionals, a ? would be enough to handle.
let me try it and check
I have added Optional supporting example.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.