如何使用自定义对象数组对枚举进行编码
How to encode enum with Arrays of Custom Objects
提前感谢您的帮助!我是 SwiftUI 的新手,一直在努力使用自定义对象数组对枚举进行编码。这是代码:
struct ChartData: Codable {
var data: DataType
...
private enum CodingKeys : String, CodingKey { case id, title, type, info, label_x, label_y, last_update, data }
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
...
try container.encode(self.data, forKey: .data)
}
}
enum DataType: Codable{
case plot([ChartPlotData])
case slice([ChartSliceData])
case number([ChartNumberData])
}
struct ChartPlotData: Codable {
var chart_id: String
var order_plot: Int
var label_plot: String?
var points_x: [String]
var points_y: [Double]
private enum CodingKeys : String, CodingKey { case chart_id, order_plot, label_plot, points_x, points_y }
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.chart_id = try container.decode(String.self, forKey: .chart_id)
self.order_plot = try container.decode(Int.self, forKey: .order_plot)
self.label_plot = try? container.decode(String.self, forKey: .label_plot)
do{
self.points_x = try container.decode([String].self, forKey:.points_x)
}catch{
let xs = try container.decode([Double].self, forKey:.points_x)
self.points_x = xs.map { String([=10=]) }
}
self.points_y = try container.decode([Double].self, forKey:.points_y)
}
}
struct ChartSliceData: Codable {
var chart_id: String
var order_slice: Int
var label_slice: String
var value_slice: Double
}
struct ChartNumberData: Codable {
var chart_id: String
var number: Double
var unit: String?
}
我试图在 UserDefaults 中缓存 JSON 以避免必须进行无关的 API 调用。使用 JSONEncoder,我得到以下 JSON 片段(摘自更长的字符串):
"data" : {
"plot" : {
"_0" : [
{
"label_plot" : "China",
"points_y" : [
0,
0,
0,
...
但是,我希望获得这样的编码:
"data" : [
{
"label_plot" : "China",
"points_y" : [
0,
0,
0,
...
如有任何帮助,我们将不胜感激!非常感谢!
这可以通过在 CodingKeys 枚举中添加一个额外的项目来解决,用于编码和解码用于 DataType
枚举的类型,然后使用 switch
来编码和解码正确的类型数组。
这是完整的 ChartData 结构,但为简洁起见删除了一些属性和代码
struct ChartData: Codable {
var id: Int
var title: String
var data: DataType
enum CodingKeys: String, CodingKey {
case id, title, data, type
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(title, forKey: .title)
switch data {
case .number(let values):
try container.encode("number", forKey: .type)
try container.encode(values, forKey: .data)
case .plot(let values):
try container.encode("plot", forKey: .type)
try container.encode(values, forKey: .data)
case .slice(let values):
try container.encode("slice", forKey: .type)
try container.encode(values, forKey: .data)
}
}
init(from decoder: Decoder) throws {
var container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(Int.self, forKey: .id)
title = try container.decode(String.self, forKey: .title)
let type = try container.decode(String.self, forKey: .type)
switch type {
case "number":
let values = try container.decode([ChartNumberData].self, forKey: .data)
data = .number(values)
// case ...
default:
fatalError("Unsupported type for DataType: \(type)")
}
}
}
提前感谢您的帮助!我是 SwiftUI 的新手,一直在努力使用自定义对象数组对枚举进行编码。这是代码:
struct ChartData: Codable {
var data: DataType
...
private enum CodingKeys : String, CodingKey { case id, title, type, info, label_x, label_y, last_update, data }
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
...
try container.encode(self.data, forKey: .data)
}
}
enum DataType: Codable{
case plot([ChartPlotData])
case slice([ChartSliceData])
case number([ChartNumberData])
}
struct ChartPlotData: Codable {
var chart_id: String
var order_plot: Int
var label_plot: String?
var points_x: [String]
var points_y: [Double]
private enum CodingKeys : String, CodingKey { case chart_id, order_plot, label_plot, points_x, points_y }
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.chart_id = try container.decode(String.self, forKey: .chart_id)
self.order_plot = try container.decode(Int.self, forKey: .order_plot)
self.label_plot = try? container.decode(String.self, forKey: .label_plot)
do{
self.points_x = try container.decode([String].self, forKey:.points_x)
}catch{
let xs = try container.decode([Double].self, forKey:.points_x)
self.points_x = xs.map { String([=10=]) }
}
self.points_y = try container.decode([Double].self, forKey:.points_y)
}
}
struct ChartSliceData: Codable {
var chart_id: String
var order_slice: Int
var label_slice: String
var value_slice: Double
}
struct ChartNumberData: Codable {
var chart_id: String
var number: Double
var unit: String?
}
我试图在 UserDefaults 中缓存 JSON 以避免必须进行无关的 API 调用。使用 JSONEncoder,我得到以下 JSON 片段(摘自更长的字符串):
"data" : {
"plot" : {
"_0" : [
{
"label_plot" : "China",
"points_y" : [
0,
0,
0,
...
但是,我希望获得这样的编码:
"data" : [
{
"label_plot" : "China",
"points_y" : [
0,
0,
0,
...
如有任何帮助,我们将不胜感激!非常感谢!
这可以通过在 CodingKeys 枚举中添加一个额外的项目来解决,用于编码和解码用于 DataType
枚举的类型,然后使用 switch
来编码和解码正确的类型数组。
这是完整的 ChartData 结构,但为简洁起见删除了一些属性和代码
struct ChartData: Codable {
var id: Int
var title: String
var data: DataType
enum CodingKeys: String, CodingKey {
case id, title, data, type
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(title, forKey: .title)
switch data {
case .number(let values):
try container.encode("number", forKey: .type)
try container.encode(values, forKey: .data)
case .plot(let values):
try container.encode("plot", forKey: .type)
try container.encode(values, forKey: .data)
case .slice(let values):
try container.encode("slice", forKey: .type)
try container.encode(values, forKey: .data)
}
}
init(from decoder: Decoder) throws {
var container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(Int.self, forKey: .id)
title = try container.decode(String.self, forKey: .title)
let type = try container.decode(String.self, forKey: .type)
switch type {
case "number":
let values = try container.decode([ChartNumberData].self, forKey: .data)
data = .number(values)
// case ...
default:
fatalError("Unsupported type for DataType: \(type)")
}
}
}