Как прочитать json на swift с нулевыми клавишами и используя значения по умолчанию? - PullRequest
0 голосов
/ 29 апреля 2020

У меня есть класс, определенный как:

struct MyObject: Identifiable{
    var id = UUID()
    var paramA: String
    var paramB: String
    var paramC: String

    init(paramA: String, paramB: String = "default", paramC: String = "tomato"  ){
        self.paramA = paramA
        self.paramB = paramB
        self.paramC = paramC
    }
}

Для чтения Json Я использую landmarkData

let landmarkData: [Landmark] = load("inputData.json")

func load<T: Decodable>(_ filename: String) -> T {  
    let data: Data

    guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
        else {
            fatalError("Couldn't find \(filename) in main bundle.")
    }

    do {
        data = try Data(contentsOf: file)
    } catch {
        fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
    }

    do {
        let decoder = JSONDecoder()
        return try decoder.decode(T.self, from: data)
    } catch {
        fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
    }
}

Я решил, что данные также могут поступать через Json, поэтому я изменил структуру MyObject (добавив Hashable, Codable и изменив var id = UUID () для Int и перейдя к параметру)

struct MyObject: **Hashable, Codable**, Identifiable{
    **var id = Int**
    var paramA: String
    var paramB: String
    var paramC: String

    init(**id : Int,** paramA: String, paramB: String = "default", paramC: String = "tomato"  ){
        **self.id = id**
        self.paramA = paramA
        self.paramB = paramB
        self.paramC = paramC
    }
}

Это работает с Json со всеми ключами на каждом объекте. Но я бы не хотел определять ключи, которые будут принимать значение по умолчанию (ключи paramA и paramB). И мне не нужно определять идентификатор в Json.

inputData. json

 [{
    "paramA": "Hello",
    "paramB": "World",
    "paramC": "!!!",
 },
 {
    "paramA": "Hi",
 },
 {
    "paramA": "Hello",
    "paramC": "??",
 }]

1 Ответ

0 голосов
/ 04 мая 2020

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

struct MyObject: Identifiable{
    var id = UUID()
    var paramA: String
    var paramB: String
    var paramC: String

    init(paramA: String, paramB: String = "default", paramC: String = "tomato"  ){
        self.paramA = paramA
        self.paramB = paramB
        self.paramC = paramC
    }

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

       do {
            paramB = try values.decode(String.self, forKey: .paramB)
          }
          catch {
            paramB = "default"
          }

       do {
            paramC = try values.decode(String.self, forKey: .paramC)
          }
          catch {
            paramC = "default"
          }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...