我有以下的Swift结构体。
我需要将其编码为一个具有以下格式的JSON对象:
struct Session: Encodable {
let sessionId: String
}
struct Person: Encodable {
let name: String
let age: Int
}
let person = Person(name: "Jan", age: 36)
let session = Session(sessionId: "xyz")
我需要将其编码为一个具有以下格式的JSON对象:
{
"name": "Jan",
"age": 36,
"sessionId": "xyz"
}
将Session
的所有键合并到Person
的键中
我考虑使用一个带有自定义Encodable
实现的容器结构,其中使用SingleValueEncodingContainer
,但它显然只能编码一个值
struct RequestModel: Encodable {
let session: Session
let person: Person
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(person)
// crash
try container.encode(session)
}
}
let person = Person(name: "Jan", age: 36)
let session = Session(sessionId: "xyz")
let requestModel = RequestModel(session: session, person: person)
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let data = try encoder.encode(requestModel)
let json = String(data: data, encoding: .utf8)!
print(json)
由于网络API是固定的,我无法更改json格式。虽然我可以将sessionId
作为Person
的属性,但我希望避免这样做,因为它们是不相关的模型。
另一种方式是让RequestModel
从Session
和Person
复制所有属性,如下所示,但这并不好,因为我的实际结构有更多的属性。
struct RequestModel: Encodable {
let sessionId: String
let name: String
let age: Int
init(session: Session, person: Person) {
sessionId = session.sessionId
name = person.name
age = person.age
}
}
encode(to:)
实现中,你指定要使用单值容器。因此,输出只能包含一个值,所以后续编码会覆盖它。如果你需要将多个对象组合成一个 JSON 输出,请确保它们都使用相同类型的容器,并且该容器必须是键控或非键控值容器,具体取决于你想让你的 JSON 是数组还是字典。不要混用,也不要使用单值容器。 - Ash