使用jSONEncoder的自定义结构

时间:2018-02-10 06:52:14

标签: swift serialization encodable jsonencoder

想要使用JSONEncoder + Encodable将对象编码为自定义结构。

struct Foo: Encodable {
   var name: String?
   var bars: [Bar]?
}

struct Bar: Encodable {
   var name: String?
   var value: String?
}

let bar1 = Bar(name: "bar1", value: "barvalue1")
let bar2 = Bar(name: "bar2", value: "barvalue2")
let foo = Foo(name: "foovalue", bars: [bar1, bar2])

编码foo的默认方法给出:

let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let data = try encoder.encode(foo)
print(String(data: data, encoding: .utf8)!)

输出:

{
   "name": "foovalue",
   "bars": [
      {
         "name": "bar1",
         "value": "barvalue1"
      },
      {
         "name": "bar2",
         "value": "barvalue2"
      }
   ]
}

在自定义输出中,我希望使用属性name的值作为键,并将rest的值作为上述键的值。这同样适用于嵌套对象。所以我希望输出为:

{
    "foovalue": [
       {
          "bar1": "barvalue1"
       },
       {
          "bar2": "barvalue2"
       }
     ]
}

问题是Encodable / JSONEncoder是否支持此功能。现在我只处理第一个输出字典并通过迭代键重组它。

1 个答案:

答案 0 :(得分:1)

如果您想保留FooBar Encodable,可以通过提供使用特定编码密钥的自定义encode(to:)来实现此目的,该密钥的值为{ {1}}:

name

private struct StringKey: CodingKey { let stringValue: String var intValue: Int? { return nil } init(_ string: String) { stringValue = string } init?(stringValue: String) { self.init(stringValue) } init?(intValue: Int) { return nil } } struct Foo: Encodable { var name: String var bars: [Bar] func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: StringKey.self) try container.encode(bars, forKey: StringKey(name)) } } struct Bar : Encodable { var name: String var value: String func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: StringKey.self) try container.encode(value, forKey: StringKey(name)) } } 可以采用任意StringKey值,允许您根据需要随意编码。