我是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": []
}
]
}
]
}