Search code examples
jsonswiftcodableswift5decodable

Swift Json Decodable data structure, varying values in single array


what im working with

"meta_data": [
        {
            "id": 4116,
            "key": "_wcf_frm_created",
            "value": ""
        },
        {
            "id": 4117,
            "key": "_wcf_custom_degin_checkbox",
            "value": ""
        },
        {
            "id": 4118,
            "key": "_wcf_frm_data",
            "value": {
                "1": {
                    "1": "",
                    "2": "",
                    "3": "chk_box"
                }
            }
        },
        {
            "id": 4142,
            "key": "_vendor_select",
            "value": "6484"
        },
        {
            "id": 4143,
            "key": "_vendor_percentage",
            "value": "100"
        },
        {
            "id": 4144,
            "key": "_vendor_pro_cat",
            "value": "Sushi"
        },
        {
            "id": 4156,
            "key": "slide_template",
            "value": "default"
        }
    ],
    "_links": {
        "self": [
            {
                "href": "https://xxxxxx.net/wp-json/wc/v3/products/6489"
            }
        ],
        "collection": [
            {
                "href": "https://xxxxxx.net/wp-json/wc/v3/products"
            }
        ]
    }

what I currently have

struct woocomerceProduct : Decodable, Encodable
{
    var meta_data : [Meta_data?]
    var _links : [_Links?]


}

    struct Meta_data : Decodable, Encodable
{
    var id : Int?
    var key : String?
    var value : String?
}
   struct One : Decodable, Encodable
{
        var one : String?
        var two : String?
        var three : String?
}

struct _Links : Decodable, Encodable
{
    var SELF : [String?]
    var collectio : [String?]
}

ok so here are the questions. 1. id 4118. value goes from String to obj, how do I code this part? 2. it also uses a variable string "1","2"... I can't use integer as variable, so I spelled it out? should be ok. 3. The value here is self, I can't use a variable self cause it will think it's a self property. so I just capitalized this.

I looked at this, which i believe is something similar to what i need to do, but since this is between an object and an string, im not sure what i need to code here. Swift structures: handling multiple types for a single property


Solution

  • Try this link for conversion of your json into Codable model link

        import Foundation
    
    // MARK: - Welcome
    struct Welcome: Codable {
        let metaData: [MetaDatum]
        let links: Links
    
        enum CodingKeys: String, CodingKey {
            case metaData = "meta_data"
            case links = "_links"
        }
    }
    
    // MARK: - Links
    struct Links: Codable {
        let linksSelf, collection: [Collection]
    
        enum CodingKeys: String, CodingKey {
            case linksSelf = "self"
            case collection
        }
    }
    
    // MARK: - Collection
    struct Collection: Codable {
        let href: String
    }
    
    // MARK: - MetaDatum
    struct MetaDatum: Codable {
        let id: Int
        let key: String
        let value: ValueUnion
    }
    
    enum ValueUnion: Codable {
        case string(String)
        case valueClass(ValueClass)
    
        init(from decoder: Decoder) throws {
            let container = try decoder.singleValueContainer()
            if let x = try? container.decode(String.self) {
                self = .string(x)
                return
            }
            if let x = try? container.decode(ValueClass.self) {
                self = .valueClass(x)
                return
            }
            throw DecodingError.typeMismatch(ValueUnion.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for ValueUnion"))
        }
    
        func encode(to encoder: Encoder) throws {
            var container = encoder.singleValueContainer()
            switch self {
            case .string(let x):
                try container.encode(x)
            case .valueClass(let x):
                try container.encode(x)
            }
        }
    }
    
    // MARK: - ValueClass
    struct ValueClass: Codable {
        let the1: [String: String]
    
        enum CodingKeys: String, CodingKey {
            case the1 = "1"
        }
    }