Home > Enterprise >  decode json with dynamic coding keys
decode json with dynamic coding keys

Time:10-10

I have a JSON file that contains details about cryptocurrency with a key that changes (you can see after data there are 1,2 and so on) I did some research and realized that I need to use a dictionary (as defined in struct coin info) the problem is that I get an error - "Expected to decode Dictionary<String, Any> but found a string/data instead.", underlying error: nil))

I would appreciate an explanation of what the problem is and where I am wrong.

my structs:

struct CoinsInfo:Codable {
    
    
    let data:[String:CoinSpecificInfo]?
  
}

struct CoinSpecificInfo:Codable {
    let urls:UrlsCoins?
    let logo:String?
    let id:Int?
    let symbol:String?
    

}

struct UrlsCoins:Codable {
    
    let website:[CoinWebsites]?
    let twitter:[CoinTwitters]?
    let facebook:[CoinFacebook]?
    let explorer:[CoinExplorer]?
    let reddit:[CoinReddits]?
    
    
}
struct CoinWebsites:Codable {
    
    let website:String?
    
}
struct CoinTwitters:Codable {
    
    let urlTwitters:String?
    
}
struct CoinFacebook:Codable {
    
    let urlFacebook:String?
    
}
struct CoinExplorer:Codable {
    
    
    let urlExplorer:String?
    
}
struct CoinReddits:Codable {
    
    let urlEReddits:String?
    
}

json format:

{
   "status":{
      "timestamp":"2022-10-09T11:11:11.686Z",
      "error_code":0,
      "error_message":null,
      "elapsed":1,
      "credit_count":1,
      "notice":null
   },
   "data":{
      "1":{
         "urls":{
            "website":[
               "pthkfb543fm",
               "49xjybh5mlq",
               "0uux1lvt44id",
               "kqb4lyfeos",
               "rbh8ui7r9dj",
               "0em815h34ay9",
               "zhmg6phhpmd",
               "z6smii44j5",
               "59bf5ofx2h4",
               "95l4hn2qvr6"
            ],
            "technical_doc":[
               "oid34tehsbb",
               "d1ofa6b2hbg",
               "9l1xpu1bo7",
               "ped2a98gup",
               "y951pv6v55e",
               "9tqxaa6capo",
               "hssug4slmc6",
               "28ocf6dnc3i",
               "cddlngcaboe",
               "xka0x1dijb"
            ],
            "twitter":[
               
            ],
            "reddit":[
               "sbv1ndmtcb",
               "wlu5zd1d2jq",
               "o2b8f0xek3",
               "70l3icwp1sd",
               "pmcm26nvg7d",
               "xz4idaq8at",
               "utaqexwga6",
               "px7o0o4e2f",
               "ginsnepn93i",
               "mqfaedmq29"
            ],
            "message_board":[
               "umt9tn7giq",
               "n37dd8jqkq",
               "b8j4r5gdoio",
               "9hsoy1y579b",
               "twexsn7t5di",
               "v52nrhmnrc",
               "jy5hui32j8k",
               "sssb806c71m",
               "t8sm0f2i1t",
               "tm5osp7fstg"
            ],
            "announcement":[
               
            ],
            "chat":[
               
            ],
            "explorer":[
               "opde5rdke6",
               "r6qhe54rmpl",
               "eoj3z1xqssm",
               "i09e7oxtj1b",
               "rfah6o4912n",
               "jrju212ljoo",
               "oeyzlewitpi",
               "o8l7lk1tsiq",
               "iwms7fi859p",
               "er098njihii"
            ],
            "source_code":[
               "grkckgsnlxd",
               "nl208dwuitg",
               "f09za84abdw",
               "dq5319hlyag",
               "ycf03rrymip",
               "tf76bcn0w9f",
               "2e0vl41amhw",
               "ztpq27uwj3m",
               "l3j3x6hnx5k",
               "zj1c4cl13j"
            ]
         },
         "logo":"d0ln7k9juc",
         "id":1,
         "name":"blntl59cjh",
         "symbol":"iaeaxzvx5jd",
         "slug":"1y0k474cv1d",
         "description":"i72hjlt621l",
         "date_added":"2022-10-09T11:11:11.686Z",
         "date_launched":"2022-10-09T11:11:11.686Z",
         "tags":[
            "n2jbg87vff",
            "vr7mthp6s7",
            "0vbnftw8hqz",
            "h2vhpc39dwf",
            "ocdozsqcv3",
            "0sry86fib7k9",
            "nqkgqwmhon",
            "a6hlvwuv7o",
            "n37q9hsx66a",
            "8edmkawhdlq"
         ],
         "platform":null,
         "category":"w4w9ris8y9p"
      },
      "2":{
         "urls":{
            "website":[
               "3fnvimztsqo",
               "obpgb3o03qc",
               "3rzbwjniljp",
               "lwzp3g0l7qn",
               "pj9i9esmycd",
               "rxxqdzsh74h",
               "c3h167i3gn9",
               "nhztuwzrbqo",
               "lu7gi5qm4fq",
               "pmxizdq4j1"
            ],
            "technical_doc":[
               "ucnmd1rwgji",
               "zxqw8ajty5",
               "tihr9s3f69",
               "l3ba21297z",
               "54kuohb05xn",
               "ml74ors5ltc",
               "utnqamn2ud9",
               "4wg8lcx8pbr",
               "abhp5ohx12b",
               "4fc1smpj5ps"
            ],
            "twitter":[
               
            ],
            "reddit":[
               "alimp4er63t",
               "urpga0uwill",
               "dl68fd2bq8f",
               "vp8mgbjcbv",
               "w6p16dbnv5s",
               "q8dvzg90d",
               "1dkfx8g4f1ui",
               "oederkt3df",
               "00d49eblt6j3l",
               "ywcnpmio49s"
            ],
            "message_board":[
               "cqoizsyx8mn",
               "vqxjb3g2y2r",
               "9oadavn71xm",
               "ew9qubh8x4n",
               "czbbkpt4egu",
               "jbx26vqega",
               "kynzrmrazae",
               "s5twwsy7bw",
               "rw7oep10pj",
               "xqoyj0kc79q"
            ],
            "announcement":[
               
            ],
            "chat":[
               
            ],
            "explorer":[
               "ioac8iuqyma",
               "v9xm5fpid7",
               "hssvwnwhe17",
               "9o77col8hk4",
               "b6tr44woibq",
               "3zoyuxe9s2z",
               "eeh948ksf9o",
               "qdhnncab0po",
               "z80tc2ztsh",
               "xki8g0zw8vh"
            ],
            "source_code":[
               "q5njdmu1tvp",
               "rswxz9717k",
               "fchf720dx3",
               "rzzfhi5mk3g",
               "t3qzejl5gt",
               "qm22rerkrc",
               "11lgg2etg4l",
               "0dru9zhnof7",
               "l2x2n8ueq0c",
               "z33p76whb7c"
            ]
         },
         "logo":"jywrmmc68g",
         "id":2,
         "name":"uiyzzwog9d",
         "symbol":"gy73ckf5l1v",
         "slug":"ki7li2ah6l",
         "description":"o7v6hhf1qce",
         "date_added":"2022-10-09T11:11:11.686Z",
         "date_launched":"2022-10-09T11:11:11.686Z",
         "tags":[
            "157427ygz4v",
            "u5iba7d9yt",
            "89xtswitklk",
            "l8mwl50329c",
            "av0ty13yxi8",
            "27luj3irtrj",
            "6bqwzp1w7lr",
            "7zusdyi69od",
            "kwxa2knt0dn",
            "hpsc19nhm67"
         ],
         "platform":null,
         "category":"1jrjafok03s"
      }
   }
}

CodePudding user response:

I would appreciate an explanation of what the problem is and where I am wrong.

The problem is that the website, twitter, facebook, explorer, reddit keys are arrays of strings in the JSON response not arrays of custom objects so if you change the UrlsCoins to:

struct UrlsCoins:Codable {

    let website:[String]?
    let twitter:[String]?
    let facebook:[String]?
    let explorer:[String]?
    let reddit:[String]?
}

You will be able to parse the JSON

CodePudding user response:

The problem you have is that the models you have do not match the json data you get from the server.

Try these structs models, mostly obtained from app.quicktype.io , and use them like as shown, to decode the server response (works well for me).

By inspection, you can find the differences between your models and "my" models that can decode the json data.

let results = try JSONDecoder().decode(InfoResponse.self, from: data)



// MARK: - InfoResponse
struct InfoResponse: Codable {
    let status: Status
    let data: [String: Datum]
}

// MARK: - Datum
struct Datum: Codable {
    let urls: Urls
    let logo: String
    let id: Int
    let name, symbol, slug, datumDescription: String
    let dateAdded, dateLaunched: String
    let tags: [String]
    let platform: String?
    let category: String

    enum CodingKeys: String, CodingKey {
        case urls, logo, id, name, symbol, slug
        case datumDescription = "description"
        case dateAdded = "date_added"
        case dateLaunched = "date_launched"
        case tags, platform, category
    }
}

// MARK: - Urls
struct Urls: Codable {
    let website, technicalDoc: [String]
    let twitter: [String]
    let reddit, messageBoard: [String]
    let announcement, chat: [String]
    let explorer, sourceCode: [String]

    enum CodingKeys: String, CodingKey {
        case website
        case technicalDoc = "technical_doc"
        case twitter, reddit
        case messageBoard = "message_board"
        case announcement, chat, explorer
        case sourceCode = "source_code"
    }
}

// MARK: - Status
struct Status: Codable {
    let timestamp: String
    let errorCode: Int
    let errorMessage: String?
    let elapsed, creditCount: Int
    let notice: String?

    enum CodingKeys: String, CodingKey {
        case timestamp
        case errorCode = "error_code"
        case errorMessage = "error_message"
        case elapsed
        case creditCount = "credit_count"
        case notice
    }
}

You will have to check the docs, to determine which properties are optional. In that case add a ? to it.

  • Related