使用 jSONEncoder 的自定义结构
Custom structure using 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 是否支持这个。现在我只是处理第一个输出字典并通过迭代键来重构它。
如果您想保留 Foo
和 Bar
Encodable
,您可以通过提供自定义 encode(to:)
来实现,该自定义 encode(to:)
使用特定的编码键,其值是 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
可以取任何 String
值,允许您根据需要任意编码。
想要使用 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 是否支持这个。现在我只是处理第一个输出字典并通过迭代键来重构它。
如果您想保留 Foo
和 Bar
Encodable
,您可以通过提供自定义 encode(to:)
来实现,该自定义 encode(to:)
使用特定的编码键,其值是 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
可以取任何 String
值,允许您根据需要任意编码。