Расшифровка JSON и сопоставление его с существующим объектом Swift - PullRequest
2 голосов
/ 10 февраля 2020

У меня есть следующий объект

struct Properties: Decodable {
    var id: String?
    var value: String?
    var color: String?
}

В первом запросе к серверу я получаю следующий ответ

{ 
   "id":"1",
   "color":"red"
}

И после другого запроса я получаю

{ 
   "id":"1",  // the id of the object props is meant for 
   "props":{ 
      "value":"my value" // I can get any property here
   }
}

После двух запросов у меня должен быть установлен объект со всеми свойствами

. Сейчас я декодирую второй запрос следующим образом

struct SetAttr: Decodable {

    let id: String
    let props: [String : Any]

    enum SetAttrCodingKeys: String, CodingKey {
        case id
        case props
    }

    init(from decoder: Decoder) throws {

        let container = try! decoder.container(keyedBy: SetAttrCodingKeys.self)
        props = try! container.decode([String : Any].self, forKey: .props)
        id = try! container.decode(String.self, forKey: .id)

    }
}

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

РЕДАКТИРОВАТЬ:

Вот как я пытался установить свойства из словаря, но решение не масштабируемый

var myObject: Properties
properties = setAttr.props // [String:Any]

let keys = properties.keys

keys.forEach { key in

    if let value = properties[key] {

        switch key {
        case "value":
            myObject.value = value as? String
        case "color":
            myObject.color = value as? String
        default:
            break
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 10 февраля 2020

Есть разные способы сделать это, но одним из возможных способов может быть что-то вроде этого:

struct SecAttr: Decodable {
    let id: String
    var props: Properties?

    private enum CodingKeys: String, CodingKey {
       case id
       case props
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        id = try container.decode(String.self, forKey: .id)

        if let props = try container.decodeIfPresent(Properties.self, forKey: .props) {
          self.props = props
        } else {
          // decode Properties from the same object
          self.props = try Properties(from: decoder)
        }
    }
}

struct Properties: Decodable {
    var value: String?
    var color: String?

    mutable update(from props: Properties) {
       value = props.value ?? value
       color = color.value ?? color
    }
}

Теперь вы можете декодировать свой исходный объект и после получения обновленных свойств просто обновите их на оригинальном.

0 голосов
/ 10 февраля 2020

Просто используйте JSONSerialization, который разбирает все, что вы в него бросаете, в массивы и словари. Это освобождает вас от всех проблем, которые у вас возникают со странно отформатированным JSON.

Например, второй запрос будет проанализирован как словарь с двумя ключами «id» и «props», а «props» имеет значение, которое снова является словарем с одним ключом «value» и значением «моя ценность».

И, пожалуйста, прекратите использовать попытку! Это заставит ваше приложение мгновенно обработать sh, если какой-либо ввод не ожидается. Неожиданные входы должны обрабатываться, а не приводить к взлому sh.

...