0

I have a really big JSON coming from server but the conversion to Model object is failing .

I have tried a lot of fix for the same but none of them works

So i extracted a single key with some values which mirrors a Model

How it looks inside the big JSON (appConfig is one of the many keys)

\"appConfig\":\"{\\\"launcherAfterLogin\\\":\\\"ma.dista.activities.jobs.JobListingActivity\\\",\\\"logging\\\":true,\\\"crashReport\\\":true,\\\"defaultLanguage\\\":\\\"en-US\\\"}\"

How it looks when i extracted it out and assigned it to a String variable

{\"appConfig\":\"{\\\"launcherAfterLogin\\\":\\\"activities.jobs.JobListingActivity\\\",\\\"logging\\\":true,\\\"crashReport\\\":true,\\\"defaultLanguage\\\":\\\"en-US\\\"}\"}

I created a Model to map this JSON to

struct Config: Decodable {
    let appConfig: AppConfig
}

struct AppConfig: Decodable {
    let launcherAfterLogin: String?
    let logging: Bool?
    let crashReport: Bool?
    let defaultLanguage: String?
    let updateUrl: String?
    let imageUploadAsPDF: Bool?
}

Then i use the code below to map the JSON to the Model

let jsonStringModified = "{\"appConfig\":\"{\\\"launcherAfterLogin\\\":\\\"activities.jobs.JobListingActivity\\\",\\\"logging\\\":true,\\\"crashReport\\\":true,\\\"defaultLanguage\\\":\\\"en-US\\\"}\"}"

let jsonData = jsonStringModified.data(using: .utf8)!

do {
    let jsonModel = try JSONDecoder().decode(Config.self, from: jsonData)
    print(jsonModel)
} catch let error as NSError {
    print(error)
}

Now, when i run this, it crashes with this error

Error Domain=NSCocoaErrorDomain Code=4864 "Expected to decode Dictionary but found a string/data instead." UserInfo={NSCodingPath=( "CodingKeys(stringValue: \"appConfig\", intValue: nil)" ), NSDebugDescription=Expected to decode Dictionary but found a string/data instead.}

I also tried converting this Data value to JSONSerialised Dictionary and then back to JSONSerialised Data which i then fed to the JSONDecoder

do {
    if let jsonSerialised = try JSONSerialization.jsonObject(with: jsonData, options: .allowFragments) as? [String: Any] {

        let jsonSerialisedUpdated = try JSONSerialization.data(withJSONObject: jsonSerialised, options: .prettyPrinted)

        let jsonModel = try JSONDecoder().decode(Config.self, from: jsonData)

        print(jsonModel)
    }

} catch let error as NSError {
    print(error)
}

But facing the same error here as well

Also, in my Big JSON, only this key(appConfig) was crashing out of all the keys everytime i ran

UPDATE :

Actually this whole Config model is coming in as a String which has various keys inside it like appConfig and others and i am creating a parser to convert this Config as String to a Config as Model

struct BiggerConfig: Decodable {
    let otherConfig: CustomType
    let config: String // I want to convert this String to Config type which has keys like appConfig inside it
}

The config above is actually a JSON but it coming as a String from the server and i wanted to create a parser for it

user121095
  • 697
  • 2
  • 6
  • 18
  • That isn't valid JSON is it... – trojanfoe Sep 30 '19 at 09:32
  • As the error clearly states the value for key `appConfig` is not a dictionary. It's another **JSON string** which must be decoded on a second level. The format to send nested JSON strings is pretty silly by the way. – vadian Sep 30 '19 at 09:33
  • Quickly and badly: https://pastebin.com/Eb3bKNZS But you might get the idea ;) Override the `init()` might be the key – Larme Sep 30 '19 at 09:44
  • @Larme Wow that worked, but how ? – user121095 Sep 30 '19 at 09:48
  • Because it's as I named the var `jsonStringified`. It's JSON Stringified within JSON. So you need to convert back the String as a Data, and decode it back. Step by step. As you did from `jsonData` to Config, then, read the value as a String, convert it back to Data, let the JSONDecoder do it from there... – Larme Sep 30 '19 at 09:50

1 Answers1

0

The problem is that your JSON string is structured differently to what you think. If we remove all the escaping, the JSON you have is this:

{"appConfig" : "{\"launcherAfterLogin\":\"activities.jobs.JobListingActivity\",\"logging\":true,\"crashReport\":true,\"defaultLanguage\":\"en-US\"}"}

The appConfig key's value is a string that contains another escaped JSON string.

To fix this, either get the incoming JSON fixed or decode appConfig as a string and then decode that string as a Config object

JeremyP
  • 84,577
  • 15
  • 123
  • 161