2

With in Server response sometimes missing "tags" key. How we have to write codable struct for this response.

[
  {
    "product_id": 10
    "product_name": "Bulb"
    "tags": ["x", "y", "z"]
  },
  {
    "product_id": 11
    "product_name": "Wire"
  }
]

decoding like this

do {

    // decoding...
    let product_model = try JSONDecoder().decode([ProductItem].self, from: data)

} catch let error {

    print("Product list error(decoder): \(error.localizedDescription)") 
}

// Product structure

struct ProductItem: Codable {

    // variables
    let product_id: String?
    let product_name: String?
    let tags: [String]?

    // alternative keys...
    private enum CodingKeys: String, CodingKey {

        case product_id
        case product_name
        case tags // what i have to do here
    }
}
1
  • Paste json here and select SWIFT CODABLE in code template. It will generate codable struct for you. Commented May 6, 2019 at 8:08

3 Answers 3

3

It looks like you JSON is not correct. It should look similar to this one:

[
  {
    "product_id": 10,
    "product_name": "Bulb",
    "tags": ["x", "y", "z"]
  },
  {
    "product_id": 11,
    "product_name": "Wire"
  }
]

and for that, your structure should be similar to:

struct ProductItem: Codable {

    // variables
    let product_id: Int
    let product_name: String
    let tags: [String]?
}

You don't have to provide CodingKeys if your variables in the structure are named the same as keys in JSON object. Also, keep in mind that "product_id": 10, is a number so you should use Int not a String.

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

1 Comment

Yes correct "CodingKeys" no need. But based on the products json coming like this.
2

Your JSON is missing some commas, the correct JSON is:

[
    {
        "product_id": 10,
        "product_name": "Bulb",
        "tags": ["x", "y", "z"]
    },
    {
        "product_id": 11,
        "product_name": "Wire"
    }
]

The product_id in your code is a String, whereas in your JSON, it is a number.

Swift can actually handle missing keys like this, as long as you make the property optional, which you have correctly done here. tags will be assigned nil when there is no key in the JSON. So you don't really have to do anything other than changing product_id to be a Int.

Your property names can also be renamed to be more Swifty if you use convertFromSnakeCase option when decoding:

struct ProductItem: Codable {

    let productId: Int?
    let productName: String?
    let tags: [String]?
}

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let decoded = try! decoder.decode([ProductItem].self, from: data)
print(decoded[1].tags) // nil

11 Comments

You can write the code even more Swifty by removing the CodingKeys and adding the .convertFromSnakeCase strategy 😉
if all keys coming correctly, this is correct. if tags key missing in few products. what we have to do.
@KondaYadav It doesn't matter. You don't have to do anything. ProductItem.tags will simply be nil. It won't crash. Do you want to assign it a default value?
@Sweeper I'm getting like this ERROR: The data couldn’t be read because it isn’t in the correct format.
@KondaYadav Ah that's because your JSON is still invalid. I thought you fixed it in your edit, but the JSON still seems to be missing some commas. You need to somehow fix your server then.
|
0

@dahiya_boy thank you. This below code working fine.

struct ProductItem : Codable {

        let productId : Int?
        let productName : String?
        let tags : [String]?

        enum CodingKeys: String, CodingKey {
                case productId = "product_id"
                case productName = "product_name"
                case tags = "tags"
        }

        init(from decoder: Decoder) throws {
                let values = try decoder.container(keyedBy: CodingKeys.self)
                productId = try values.decodeIfPresent(Int.self, forKey: .productId)
                productName = try values.decodeIfPresent(String.self, forKey: .productName)
                tags = try values.decodeIfPresent([String].self, forKey: .tags)
        }

}

Comments

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.