0

Here's my Struct

struct UserInfo{

struct Request:Codable{
   let name = String()
}

struct Response:Codable{
   let age, weight,height,birthday:String
}

}

When I get response and all if the key match that I create, ok it's good to getting every value

but what if server pass me age, weight and height only three items

That Xcode will tell me keyNotFound "birthday"

How should I prevent this situation from decoding error?

It alway causes even else's value can't get.

I have try Optional

   let age, weight,height,birthday:String?

But it makes me in every VC need to set default value

My idea is if server has no birthday key I hope it just blank text

And the others still can get

Is it possible to achieve ?

  • https://stackoverflow.com/a/46745057/10579134 – Kedar Sukerkar Nov 01 '19 at 05:17
  • I don't understand what's the problem with optional? It is so far the safest way to handle no value situations. Why would you want to even store an empty String if the value doesn't exist? – PGDev Nov 01 '19 at 06:08
  • @PGDev If json passes keys that all I need, and I can parse correctly. but my situation is json key do not match struct key I set, it can parse failed. Even though I know you describe optional is to handle value doesn't exist but it works perfectly when both key are the same. –  Nov 01 '19 at 08:47

1 Answers1

1

If I understand your question correctly, then here's what you are looking for.

struct Response: Codable {
    let age, weight, height, birthday: String

    enum CodingKeys: String, CodingKey {
        case age = "age"
        case weight = "weight"
        case height = "height"
        case birthday = "birthday"
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        // Use your own default values after '??' operator below. I've used empty string for simplicity
        self.age = try container.decodeIfPresent(String.self, forKey: .age) ?? ""
        self.weight = try container.decodeIfPresent(String.self, forKey: .weight) ?? ""
        self.height = try container.decodeIfPresent(String.self, forKey: .height) ?? ""
        self.birthday = try container.decodeIfPresent(String.self, forKey: .birthday) ?? ""
    }
}

Here's sample usage

let serverResponse = "{\"age\": \"20\",\"number\":\"5\",\"weight\":\"80 kg\"}"
let response = try JSONDecoder().decode(Response.self, from: serverResponse.data(using: .utf8)!)
print(response)

And here's the output

Response(age: "20", weight: "80 kg", height: "", birthday: "")

serverResponse contains a key 'number' which is not present in your Response struct. But still, you can successfully decode it.