如何使用扩展名解码 JSON 嵌套字典数组:可解码?

时间:2021-03-22 11:30:35

标签: json swift codable decodable

我有这样的 JSON:

{
  "states" : [
    "C",
    "A",
    "B",
    "Sink",
  ],
  "symbols" : [
    "c",
    "a",
    "b"
  ],
  "transitions" : [
    {
      "with" : "c",
      "to" : "B",
      "from" : "C"
    },
    {
      "with" : "c",
      "to" : "Sink",
      "from" : "C"
    },
    {
      "with" : "b",
      "to" : "B",
      "from" : "B"
    },
    {
      "with" : "b",
      "to" : "Sink",
      "from" : "B"
    },
    {
      "with" : "c",
      "to" : "C",
      "from" : "A"
    },
    {
      "with" : "c",
      "to" : "Sink",
      "from" : "A"
    },
    {
      "with" : "a",
      "to" : "A",
      "from" : "A"
    },
    {
      "with" : "a",
      "to" : "Sink",
      "from" : "A"
    }
  ],
  "initialState" : "A",
  "finalStates" : [
    "B"
  ]
}

我无法解码 JSON 的 transitions 部分(我需要像苹果在 here 中那样解码)。 到目前为止我得到的是这个(评论部分是导致错误 typeMismatch(Swift.Dictionary, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Dictionary< String, Any> 但找到了一个数组。",underlyingError: nil)) )

public struct FiniteAutomata {
    let states:[String]
    let symbols:[String]
    let initialState:String
    let finalStates:[String]
    /*
    let with:[String]
    let from:[String]
    let to:[String]
     */

    enum CodingKeys: String, CodingKey {
        case states
        case symbols
        case initialState
        case finalStates
        case transitions
    }
    /*
    enum transitionInfoKeys: String, CodingKey{
        case with
        case to
        case from
    }*/
}

extension FiniteAutomata: Decodable {
    public init(from decoder: Decoder)throws{
        let decoderContainer = try decoder.container(keyedBy: CodingKeys.self)
        states = try decoderContainer.decode([String].self, forKey: .states)
        symbols = try decoderContainer.decode([String].self, forKey: .symbols)
        initialState = try decoderContainer.decode(String.self, forKey: .initialState)
        finalStates = try decoderContainer.decode([String].self, forKey: .finalStates)
        /*
        let nestedContainer = try decoderContainer.nestedContainer(keyedBy: transitionInfoKeys.self, forKey: .transitions)
        with = try nestedContainer.decode([String].self, forKey: .with)
        to = try nestedContainer.decode([String].self, forKey: .to)
        from = try nestedContainer.decode([String].self, forKey: .from)
         */
    }
}

2 个答案:

答案 0 :(得分:1)

transition 的值是一个字典数组,它变成了一个结构体数组

struct Transition : Decodable {
   let with, to, from : String
}

然后解码

let transitions : [Transition]

不需要所有 CodingKeys 和自定义 init 方法

答案 1 :(得分:1)

你需要

struct Transition: Decodable {
    let with,to,from:String
}

然后

let transitions : [Transition]

同时删除

public init(from decoder: Decoder)throws{
    let decoderContainer = try decoder.container(keyedBy: CodingKeys.self)
    states = try decoderContainer.decode([String].self, forKey: .states)
    symbols = try decoderContainer.decode([String].self, forKey: .symbols)
    initialState = try decoderContainer.decode(String.self, forKey: .initialState)
    finalStates = try decoderContainer.decode([String].self, forKey: .finalStates)
    /*
    let nestedContainer = try decoderContainer.nestedContainer(keyedBy: transitionInfoKeys.self, forKey: .transitions)
    with = try nestedContainer.decode([String].self, forKey: .with)
    to = try nestedContainer.decode([String].self, forKey: .to)
    from = try nestedContainer.decode([String].self, forKey: .from)
     */
}

因为这会自动发生,无需手动编写