首页 文章

使用Decodable解码自定义Json

提问于
浏览
0

我有这个Json:

{   "first": {
    "house": [
      "small"
    ]

  },   "second": {
    "house": [
      "small"
    ]   },   "third": {
    "car": [
      "fast",
      "economic"
    ]   },   "fourth": {
    "car": [
      "fast",
      "economic"
    ]   },   "fifth": {
    "car": [
      "fast",
      "economic"
    ],
    "ice": [
      "round",
      "tasty"
    ],
    "tree": [
      "big",
      "small"
    ]   } }

我尝试使用Decodable设置一个结构但是我没有让它工作:

struct secondLayer: Codable {
    let exchange:  [String: [String]]
}

struct decodeJson: Codable {
    let symbol: [String: [secondLayer]]

    static func decode(jsonString: String) -    [decodeJson] {
        var output = [decodeJson]()
        let decode = JSONDecoder()
        do {
            let json = jsonString.data(using: .utf8)
            output = try! decode.decode([decodeJson].self, from: json!)
        } catch {
            print(error.localizedDescription)
        }
        return output
    }
}

我收到此错误:

Fatal error: 'try!' expression unexpectedly raised an error:
Swift.DecodingError.typeMismatch(Swift.Array<Any>,
Swift.DecodingError.Context(codingPath: [], debugDescription:
"Expected to decode Array<Any    but found a dictionary instead.",
underlyingError: nil)): file
/BuildRoot/Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-900.0.74.1/src/swift/stdlib/public/core/ErrorType.swift,
line 181

我尝试了一些修改,但我没有让它工作 .

1 回答

  • 3

    错误消息

    “预计会解码数组<Any>,但会找到一个字典 . ”

    非常清楚 . 你想解码一个数组( [decodeJson] ),但根对象是一个字典(从 { 开始)

    无论如何,您的代码无法运行 . JSON中没有键 exchangesymbol .

    基本上有两种方法可以解码JSON:

    如果所有键都是 dynamic ,则无法将JSON解码为结构 . 您必须将其解码为 [String:[String:[String]]] . 在这种情况下, Codable 没有传统 JSONSerialization 的优势 .

    struct DecodeJson: Codable {
    
        static func decode(jsonString: String) -> [String:[String:[String]]] {
            var output = [String:[String:[String]]]()
            let decoder = JSONDecoder()
            do {
                let json = Data(jsonString.utf8)
                output = try decoder.decode([String:[String:[String]]].self, from: json)
                print(output)
            } catch {
                print(error.localizedDescription)
            }
            return output
        }
    }
    

    或者,如果序号键 firstsecondstatic 使用伞形结构

    struct Root : Codable {
    
        let first : [String:[String]]
        let second : [String:[String]]
        let third : [String:[String]]
        let fourth : [String:[String]]
        let fifth : [String:[String]]
    }
    
    
    struct DecodeJson {
    
        static func decode(jsonString: String) -> Root? {
    
            let decoder = JSONDecoder()
            do {
                let json = Data(jsonString.utf8)
                let output = try decoder.decode(Root.self, from: json)
                return output
            } catch {
                print(error.localizedDescription)
                return nil
            }
        }
    }
    

    当然你可以将 housecar 等解码为一个结构但这需要为每个结构自定义初始值设定项,因为你必须用 unkeyedContainer 手动解码一个数组 .

相关问题