Swift Json Декодируемая структура данных, различные значения в одном массиве

с чем я работаю

"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"
            }
        ]
    }

что у меня сейчас есть

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?]
}

хорошо, вот вопросы. 1. id 4118. значение переходит из String в obj, как мне закодировать эту часть? 2. он также использует переменную строку "1", "2"... Я не могу использовать целое число в качестве переменной, поэтому я прописал это? должно быть хорошо. 3. Здесь значение равно self, я не могу использовать переменную self, потому что она будет думать, что это свойство self. поэтому я просто написал это с большой буквы.

Я посмотрел на это, и я считаю, что это похоже на то, что мне нужно сделать, но поскольку это между объектом и строкой, я не уверен, что мне нужно здесь кодировать. Структуры Swift: обработка нескольких типов для одного свойства


person Zack Cheang Weng Seong    schedule 14.12.2019    source источник
comment
переменная _links : _Links? должен быть объектом, а массивом.   -  person Muhammad Umer Farooq    schedule 14.12.2019
comment
==› для СЕБЯ вам нужно использовать ключи кодирования. enum CodingKeys: String, CodingKey { case SELF = self }   -  person Muhammad Umer Farooq    schedule 14.12.2019


Ответы (2)


Попробуйте эту ссылку для преобразования вашего json в модель Codable ссылка

    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"
    }
}
person Vasucd    schedule 14.12.2019
comment
очень интересная ссылка, я попробую ее использовать, но здесь используется кодируемость, когда мы можем использовать декодируемость, есть ли декодируемая версия? я думаю, это не имеет значения - person Zack Cheang Weng Seong; 14.12.2019
comment
Swift 4 и более поздние версии поддерживают протокол Codable, поэтому проблем не возникнет. - person Vasucd; 14.12.2019
comment
Васу, если вы хотите прокомментировать кого-то, добавьте @ перед его именем пользователя, например, сделайте @PranavKasetti, чтобы прокомментировать Pranav. - person Hovercraft Full Of Eels; 14.12.2019
comment
@HovercraftFullOfEels хорошо - person Vasucd; 14.12.2019
comment
это сработало, спасибо за ссылку! сэкономил бы мне столько времени, если бы знал это раньше - person Zack Cheang Weng Seong; 15.12.2019
comment
@ZackCheangWengSeong наслаждайтесь :) - person Vasucd; 15.12.2019

Слишком много ненужных опций, слишком много ненужных символов подчеркивания.

  1. Для декодирования двух разных типов разумно использовать enum со связанными типами.
  2. Код декодирует словарь [String:[String:String]].
  3. Чтобы сопоставить неподходящие ключи, предоставьте CodingKeys.

struct WoocomerceProduct : Decodable {
    let metaData : [Meta]
    let links : Links

    private enum CodingKeys : String, CodingKey { case metaData  = "meta_data", links = "_links" }
}

struct Meta : Decodable {
    let id : Int
    let key : String
    let value : StringOrDictionary
}

struct Links : Decodable {
    let myself : [URLType]
    let collection : [URLType]

    private enum CodingKeys : String, CodingKey { case myself  = "self", collection }
}

struct URLType : Decodable {
    let href : URL
}


enum StringOrDictionary : Decodable {
    case string(String), dictionary([String:[String:String]])

    init(from decoder : Decoder) throws
    {
        let container = try decoder.singleValueContainer()
        do {
            let stringData = try container.decode(String.self)
            self = .string(stringData)
        } catch DecodingError.typeMismatch {
            let dictionaryData = try container.decode([String:[String:String]].self)
            self = .dictionary(dictionaryData)
        }
    }
}
person vadian    schedule 14.12.2019
comment
Я вижу, вы используете let вместо var, некоторые значения в метаданных могут быть пустыми, будет ли это работать, даже если вы написали let? - person Zack Cheang Weng Seong; 14.12.2019
comment
let - это просто объявление константы (неизменяемой). Если ключи отсутствуют, объявите соответствующие члены структуры необязательными. Кстати, удалите Encodableconfomance, если структуры никогда не будут закодированы. - person vadian; 14.12.2019
comment
imgur.com/a/DEybvQ3 если я удалю перечисление, это устранит ошибку, могу ли я переместить перечислить где-то еще? Кроме того, вы видите других, потому что это не все, что выдает API. Но ваш код реализован внизу - person Zack Cheang Weng Seong; 14.12.2019
comment
Мой ответ работает с данным JSON в вопросе. Нет смысла, если реальные данные совсем другие. Я удалю свой ответ позже. - person vadian; 14.12.2019
comment
поэтому мой ответ был imgur.com/a/Pwbpzdz, поэтому я не добавил его в общий вопрос - person Zack Cheang Weng Seong; 14.12.2019
comment
Корневой объект carteapp JSON представляет собой массив, который необходимо декодировать [WoocomerceProduct].self. И прекратите небрежно объявлять все необязательным. - person vadian; 14.12.2019
comment
Ну, я делаю это, чтобы потом не жаловаться. Поскольку я экспериментировал с Woocomerce Api, я не уверен, какой результат он может произвести, когда я начну переходить на переменный продукт. - person Zack Cheang Weng Seong; 14.12.2019