首页 > 解决方案 > Swift 节点树到复杂的 Json

问题描述

我正在开发一个用 swift 编写的工具,需要将树导出到 json。我一直遵循此处描述的 Swift 树方法作为指南。

我使用以下代码创建一棵树

class Node {
  var value: String
  var children: [Node] = []
  weak var parent: Node?

  init(value: String) {
    self.value = value
  }

  func add(child: Node) {
    children.append(child)
    child.parent = self
  }
}

let beverages = Node(value: "beverages")

let hotBeverages = Node(value: "hot")
let coffee = Node(value: "coffee")

let coldBeverages = Node(value: "cold")
let water = Node(value: "water")
let soda = Node(value: "soda")

beverages.add(child: hotBeverages)
hotBeverages.add(child: coffee)

beverages.add(child: coldBeverages)
coldBeverages.add(child: water)
coldBeverages.add(child: soda)

现在我需要将此代码导出为 json。我将它传递给 webkit,以便我可以通过 D3 加载层次结构树。这意味着我需要将其导出,使其符合以下格式...

[
 {
  "name": "beverages",
  "children": [
    {
     "name": "cold", 
     "children": [
      {"name": "water"}, 
      {"name": "soda"}
    ]},
    {
      "name": "warm", 
      "children": [
        {"name": "coffee"}
      ]
    }]
  }
]

我已经看过很多关于将 swift 导出到基本 json 的帖子,但不能完全用这样的树来完成它。任何帮助,将不胜感激!

注意:我不需要漂亮打印的 json。这只是为了这里的可读性

标签: jsonswiftmacosd3.js

解决方案


您只需要使Node符合Encodable. 您需要做的唯一棘手的步骤是仅children在包含任何元素的情况下进行编码,否则仅进行编码value。您还需要声明一个CodingKey一致性来enum告诉使用 JSON 键而不是.Encodablevaluenamevalue

extension Node: Encodable {
    private enum CodingKeys: String, CodingKey {
        case value = "name"
        case children
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(value, forKey: .value)
        if !children.isEmpty {
            try container.encode(children,forKey: .children)
        }
    }
}

然后像这样使用它

do {
    let encodedBevarages = try JSONEncoder().encode(beverages)
    print(String(data: encodedBevarages, encoding: .utf8) ?? "Encoding failed")
} catch {
    error
}

输出:

{"name":"beverages","children":[{"name":"hot","children":[{"name":"coffee"}]},{"name":"cold","儿童":[{"name":"water"},{"name":"soda"}]}]}


推荐阅读