这是打印print(String(data: encoded, encoding: .utf8) as Any)
时正确编码的主结构结构体打印编码的mainObject,然后打印结构体中的其他变量,但我希望它按顺序打印:mainAccount、mainObject、reference。
struct T: Codable {
init(){}
let mainAccount = "IMHOTECHPECOM"
let mainObject = mainObject()
let reference = UUID()
// Enum that allows easy encoding
enum CodingKeys: CodingKey {
case mainAccount, mainObject, reference;
}
// function to conform to encodable protocol
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(mainAccount, forKey: .merchantAccount)
try container.encode(mainObject.self, forKey: .mainObject)
try container.encode(reference, forKey: .reference)
}
// conforms with decodable protocol
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
_ = try container.decode(String.self, forKey: .mainAccount)
_ = try container.decode(String.self, forKey: .mainObject)
_ = try container.decode(String.self, forKey: .reference)
}
}
这是主对象
struct mainObject: Codable {
var type = "kind"
var identifier: String = ""
var guide: String = ""
init(){}
enum CodingKeys: CodingKey{
case type, identifier, guide;
}
// function to conform to encodable protocol
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(type, forKey: .type)
try container.encode(identifier, forKey: .identifier)
try container.encode(guide, forKey: .guide)
}
// conforms with decodable protocol
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
type = try container.decode(String.self, forKey: .type)
identifier = try container.decode(String.self, forKey: .identifier)
guide = try container.decode(String.self, forKey: .identifier)
}
}
这是实际视图中的功能,编码来自按钮按压的数据
func getBalance() async {
let encoder = JSONEncoder()
encoder.outputFormatting = [.sortedKeys]
encoder.outputFormatting = [.withoutEscapingSlashes]
encoder.outputFormatting = [.prettyPrinted]
guard let encoded = try? encoder.encode(mainobject) else {
print("Failed to encode")
return
}
let url = URL(string: "https://testurl.com")!
var request = URLRequest(url: url)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
do {
let (response, _) = try await URLSession.shared.upload(for: request, from: encoded)
print(String(data: encoded, encoding: .utf8) as Any)
print(String(data: response, encoding: .utf8) as Any)
} catch {
print("Encoding failed")
}
let _ = try? JSONDecoder().decode(mainObject.self, from: encoded)
在这种特殊情况下,您要求的顺序恰好符合字母顺序。因此,如果你将.sortedKeys
添加到编码器的outputFormatting
属性中,你就会得到你想要的订单:
let encoder = JSONEncoder()
encoder.outputFormatting = [.sortedKeys]
let data = try encoder.encode(myT)
这将影响JSON中所有对象中键的顺序。因此,T
的密钥将按mainAccount, mainObject, reference
的顺序输出,而mainObject
的密钥将按照guide, identifier, type
的顺序输出。
一般的答案是JSONEncoder
不记得向带键容器添加键的顺序。在内部,它使用标准Swift Dictionary
来存储键和值。Swift Dictionary
不保证对其密钥进行任何排序,每次启动程序时,顺序都可能发生变化。
如果要保证密钥的顺序得到保留,就必须编写自己的Encoder
实现,这不是一项简单的任务。