簡體   English   中英

除非嵌套是一個數組,否則Swift`Dcodable`不適用於嵌套的JSON對象

[英]Swift `Decodable` is not not working for nested JSON Objects unless the nested is an array

我已經開始轉換一些JSON解析代碼以使用新的Apple Decodable協議,並且遇到了一個在Apple測試過程中感覺太基礎的攔截器,所以我想知道我是不是在做一些愚蠢的事情。 簡而言之,我正在嘗試解析一個像這樣的JSON圖,因為我只是解碼我認為符合Decodable應該足夠了但似乎我需要符合Codable(可解碼和可編碼)以獲得所需的錯誤解碼效果:

{"keyString": {"nestedKey1" : "value1", "nestedKey1" : "value1" } }

它適用於這種情況:

{"keyString": [{"nestedKey1" : "value1", "nestedKey1" : "value1" } ]}

as是一組嵌套對象,但不是單個對象。

這是一個Swift bug還是我錯了?

這是一個可以證明問題的示例游樂場。 如果Animal類符合Decodable則它不會解析數組大小寫,但如果我將Animal設置為符合Codable那么它確實有效。 我不希望這是因為我只在這里解碼JSON。

import Foundation

//class Animal: Codable {    
class Animal: Decodable {
    var fileURLPath: String = ""
    var age: Double = 0
    var height: Double = 0
    var weight: Double = 0

    private enum CodingKeys: String, CodingKey {
        case fileURLPath = "path"
        case age
        case height
        case weight
    }

    required init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        fileURLPath = try values.decode(String.self, forKey: .fileURLPath)
        age = try values.decode(TimeInterval.self, forKey: .age)
        height = try values.decode(Double.self, forKey: .height)
        weight = try values.decode(Double.self, forKey: .weight)
    }
}

let innerObjectJSON = """
{
    "path": "tiger_pic.png",
    "age": 9,
    "height": 1.23,
    "weight": 130
}
"""

let innerObjectData = innerObjectJSON.data(using: String.Encoding.utf8)

let jsonDataNestedObject = """
    { "en" : \(innerObjectJSON)
    }
    """.data(using: String.Encoding.utf8)

let jsonDataNestedArray = """
    { "en" : [\(innerObjectJSON), \(innerObjectJSON), \(innerObjectJSON) ]
    }
    """.data(using: String.Encoding.utf8)

print("Nested Array of Objects:")

do {
    let result = try JSONDecoder().decode([String: [Animal]].self, from: jsonDataNestedArray!)
    result["en"]!.forEach ({ print($0.fileURLPath) }) // This one works
} catch { print(error) }

print("\n\n Single Object:")
do {
    let result = try JSONDecoder().decode(Animal.self, from: innerObjectData!)
        print(result.fileURLPath)
} catch { print(error) }

print("\n\nNested Object:")
do {
    let result = try JSONDecoder().decode([String: Animal].self, from:jsonDataNestedObject!)
        print(result["en"]!.fileURLPath) // I would also expect this to work but I get the error: "fatal error: Dictionary<String, Animal> does not conform to Decodable because Animal does not conform to Decodable.: file /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-900.0.45.6/src/swift/stdlib/public/core/Codable.swift, line 3420"
} catch { print(error) }

如果您不想等到下一個版本,您可以使用struct

import Cocoa

struct Animal: Codable {
    var fileURLPath: String
    var age: Double
    var height: Double
    var weight: Double

    private enum CodingKeys: String, CodingKey {
        case fileURLPath = "path"
        case age, height, weight
    }
}

let innerObjectJSON = """
{
"path": "tiger_pic.png",
"age": 9,
"height": 1.23,
"weight": 130
}
"""

let innerObjectData = innerObjectJSON.data(using: String.Encoding.utf8)

let jsonDataNestedObject = """
    { "en" : \(innerObjectJSON)
    }
    """.data(using: String.Encoding.utf8)


print("\n\nNested Object:")
do {
    let result = try JSONDecoder().decode([String: Animal].self, from:jsonDataNestedObject!)
    print(result["en"]!.fileURLPath) 
} catch { print(error) }

這給了我

Nested Object:
tiger_pic.png
["en": __lldb_expr_190.Animal(fileURLPath: "tiger_pic.png", age: 9.0, height: 1.23, weight: 130.0)]

它很容易解碼,但它不使用TimeInterval ,它只是Double的別名。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM