1
struct ProductDetails:Codable {
    var custom_attributes:[CustomAttributesData]
    struct CustomAttributesData:Codable {
        var attribute_code:String
        var value:String
    }
}

I have an Array of custom_attributes has dictionary with elements of attribute_code as String & value as String, but some value datatype's are in Array, due to Array I am not able to parse using codable, help me out, Thanks in advance

"custom_attributes": [
    {
        "attribute_code": "image",
        "value": "/6/_/6.jpg"
    },
    {
        "attribute_code": "small_image",
        "value": "/6/_/6.jpg"
    }
    {
        "attribute_code": "news_to_date",
        "value": "2017-09-30 00:00:00"
    },
    {
        "attribute_code": "category_ids",
        "value": [
            "2",
            "120"
        ]
    },
    {
        "attribute_code": "options_container",
        "value": "container2"
    }
]

I have added json above.

5
  • Post the raw JSON, not a screenshot Commented Jan 1, 2018 at 18:11
  • You have to write a custom initializer init(from decoder: Decoder). Add a do - catch block and decode String. If it throws an error decode [String] Commented Jan 1, 2018 at 18:13
  • @CodeDifferent i have changed to json. Commented Jan 1, 2018 at 18:20
  • @vadian i have done the same, so that in catch block i am getting an error 'The data couldn’t be read because it isn’t in the correct format.' Commented Jan 1, 2018 at 18:22
  • 1
    I wrote an answer. Commented Jan 1, 2018 at 18:39

1 Answer 1

3

You have to add a custom initializer which distinguishes between String and [String].

This code declares value as [String] and converts a single string to an array

struct ProductDetails : Decodable {
    let custom_attributes : [CustomAttributesData]

    struct CustomAttributesData : Decodable {

        private enum CodingKeys : String, CodingKey {
            case attributeCode = "attribute_code", value
        }

        let attributeCode : String
        let value : [String]

        init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            attributeCode = try container.decode(String.self, forKey: .attributeCode)
            do {
                let string = try container.decode(String.self, forKey: .value)
                value = [string]
            } catch DecodingError.typeMismatch {
                value = try container.decode([String].self, forKey: .value)
            } 
        }
    }
}

Alternatively you could use two separate properties stringValue and arrayValue

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.