我是Swift Codable的新手,我试图从自己编码一个“复杂”的JSON结构 . 这有点困难,因为它需要递归 .

我找到了一个关于复活枚举的堆栈溢出的解决方案,但是我没能在Swift中为我的JSON实现它 . (Swift Codable protocol with recursive enums)我得到了python的解决方案,但在Swift中要复杂得多 .

JSON文件将是这样的:

[
 {
 "id": 0,
 "name": "Simple Rule A",
     "operations": {
              "attribute": "C",
              "value": false
              }
 },
 {
 "id": 1,
 "name": "Simple Rule A",
 "operations": {
     "ruleOperator": "AND",
     "ruleOperand":[
              {
              "attribute": "A",
              "value": false
              },
              {
              "attribute": "C",
              "value": false
              }
              ]
     }
 },
 {
 "id": 2,
 "name": "Simple Rule B",
 "operations": {
 "ruleOperator": "AND",
 "ruleOperand":[
          {"ruleOperator": "OR",
          "ruleOperand":[
                   {
                   "attribute": "A",
                   "value": false
                   },
                   {
                   "attribute": "C",
                   "value": false
                   }
                   ]
          },
          {
          "attribute": "C",
          "value": false
          }
          ]
 }
 }

 ]

它是一个包含规则的数组,每个规则都有一个id和name以及操作 . 操作可以是具有操作符和操作数的“节点”,或者“叶子”作为具有属性和值的操作数 .

这就是我得到的:

import Foundation

struct Rule: Decodable {
    let id: Int
    let name: String
    let operations: Operations
}

struct Operations {

    //var ruleOperator: String

    var ruleOperator: String?
    var kind: Kind?

    enum Kind {
        case node([Operations])
        case leaf(Operand)
    }

    init(name: String, ruleOp: String, kind: Kind) {
        self.ruleOperator = ruleOp
        self.kind = kind
    }
}

extension Operations: Decodable {

    enum CodingKeys: String, CodingKey {
        case name
        case ruleOperator
        case nodes
        case test
    }

    enum CodableError: Error {
        case decoding(String)
        case encoding(String)
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)

        if let someRuleOperator = try? container.decode(String.self, forKey: .ruleOperator) {
            self.ruleOperator = someRuleOperator
        }

        if let someOperand = try container.decodeIfPresent(Operand.self, forKey: .nodes) {
            self.kind = .leaf(someOperand)
        }

        if let array = try? container.decode([Operations].self, forKey: .nodes) {
            self.kind = .node(array)
        }
        return
    }
}

struct Operand: Decodable {
    let attribute: String
    let value: Bool
}

enum Operator {
    case IS
    case AND
    case OR
    case XOR
}

问题是“init(来自解码器:解码器)”部分 . 还有“ruleOperator:String?”作为一个可选是废话 .

也许有人可以帮助我:)并给我一个正确方向的暗示 .

(同样不错的是如何使用Operator枚举而不是字符串,例如“IS”或“AND” . )

解决方案

重做JSON结构并使用此解决方案Swift Codable protocol with recursive enums

{
 "id": 1,
 "name": "Simple Rule A",
 "operations": [
                   {
                   "attribute": "AND",
                   "value": null,
                   "operations": [
                                {
                                "attribute": "A",
                                "value": true,
                                "operations": []
                                },
                                {
                                "attribute": "B",
                                "value": true,
                                "operations": []
                                }
                                ]
                   }
               ]
 }