Как установить / скопировать свойство Struct при декодировании JSON содержимого - PullRequest
0 голосов
/ 09 апреля 2020

У меня есть одна структура для декодирования содержимого json:

struct CustomResponse: Decodable {
var network: String
var weight: Int = 0
var pureWeight: Int

enum CodingKeys: String, CodingKey {
    case network = "network"
    case weight = "weight"
}}

Я бы хотел установить начальное значение weight, которое анализируется из свойства JSON в pureWeight. Даже если weight будет изменено позже, pureWeight должно быть тем, которое приходит от ответа JSON.

Есть ли простой способ установить pureWeight один раз (после синтаксического анализа), не используя вручную декодировать все json содержимое?

init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
...parsing all items one by one.
}

Я использовал этот код, но, очевидно, он всегда возвращал измененные значения веса:

 var pureWeight: Int {
    get {
        return weight
    }
 }

Ответы [ 2 ]

0 голосов
/ 09 апреля 2020

Вам все еще нужен пользовательский init, но самый простой способ сделать это - let объявить свойство начального веса, поскольку оно не должно изменяться, и установить его в init

struct CustomResponse: Decodable {
    var network: String
    var weight: Int
    let pureWeight: Int

    enum CodingKeys: String, CodingKey {
        case network = "network"
        case weight = "weight"
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        network = try container.decode(String.self, forKey: .network)
        weight = try container.decode(Int.self, forKey: .weight)
        pureWeight = weight
    }
}
0 голосов
/ 09 апреля 2020

Вы можете подойти примерно так:

Сохранение init:

import Foundation

let json = """
{
    "network" : "My Awesome network",
    "weight" : 100
}
"""

struct CustomResponse: Decodable {
    var network: String
    var pureWeight: Int

    // Computed
    var weight: Int {
        get {
            return hiddenWeight ?? pureWeight
        }
        set {
            hiddenWeight = newValue
        }
    }

    // Hidden from the outside world
    private var hiddenWeight: Int?


    enum CodingKeys: String, CodingKey {
        case network
        case weight
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        network = try container.decode(String.self, forKey: .network)
        pureWeight = try container.decode(Int.self, forKey: .weight)
    }
}

let jsonDecoder = JSONDecoder()
if let data = json.data(using: .utf8),
   var response = try? jsonDecoder.decode(CustomResponse.self, from: data) {

        print(response)
        response.weight = 200
        print(response)
}

Итак, что здесь сделано, так это сохранение частной собственности, скрытой от внешнего мира. Первоначально он был установлен на nil. При анализе с JSON это nil.

При получении свойства weight мы получаем скрытое свойство hiddenWeight или weight, если hiddenWeight равно нулю.

Когда weight устанавливается на что-то, затем устанавливается hiddenWeight.

Таким образом, со следующего раза, когда запрашивается weight, возвращается hiddenWeight.

Без использования init:

Если вы хотите опустить реализацию init, вам нужно использовать любое другое имя свойства, кроме weight. Я использую myWeight.

import Foundation

let json = """
{
    "network" : "My Awesome network",
    "weight" : 100
}
"""

struct CustomResponse: Decodable {
    var network: String
    var weight: Int

    // Computed
    var myWeight: Int {
        get {
            return hiddenWeight ?? weight
        }
        set {
            hiddenWeight = newValue
        }
    }

    // Hidden from the outside world
    private var hiddenWeight: Int?
}

let jsonDecoder = JSONDecoder()
if let data = json.data(using: .utf8),
   var response = try? jsonDecoder.decode(CustomResponse.self, from: data) {

        print(response)
        response.myWeight = 200
        print(response)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...