You can use something like this to encode single values.
struct CustomBody: Codable {
let method: String
let params: [Param]
enum CodingKeys: String, CodingKey {
case method = "method"
case params = "params"
}
}
enum Param: Codable {
case bool(Bool)
case integer(Int)
case string(String)
case stringArray([String])
case valueNil
case unsignedInteger(UInt)
case optionalString(String?)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode(Bool.self) {
self = .bool(x)
return
}
if let x = try? container.decode(Int.self) {
self = .integer(x)
return
}
if let x = try? container.decode([String].self) {
self = .stringArray(x)
return
}
if let x = try? container.decode(String.self) {
self = .string(x)
return
}
if let x = try? container.decode(UInt.self) {
self = .unsignedInteger(x)
return
}
throw DecodingError.typeMismatch(Param.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for Param"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .bool(let x):
try container.encode(x)
case .integer(let x):
try container.encode(x)
case .string(let x):
try container.encode(x)
case .stringArray(let x):
try container.encode(x)
case .valueNil:
try container.encodeNil()
case .unsignedInteger(let x):
try container.encode(x)
case .optionalString(let x):
x?.isEmpty == true ? try container.encodeNil() : try container.encode(x)
}
}
}
And the usage is like this
RequestBody.CustomBody(method: "WSDocMgmt.getDocumentsInContentCategoryBySearchSource",
params: [.string(legacyToken), .string(shelfId), .bool(true), .valueNil, .stringArray(queryFrom(filters: filters ?? [])), .optionalString(sortMethodParameters()), .bool(sortMethodAscending()), .unsignedInteger(segment ?? 0), .unsignedInteger(segmentSize ?? 0), .string("NO_PATRON_STATUS")])
JSON
entry in the hash such as"date": null;
? What difference do you intend to convey by making thenull
explicit? If you plan to consume the result using Swift you will have a really hard time to tell the difference in the first place. Your link seems to be the only notable reference toencodeIfPresent
, but the case seems to be sufficiently rare to merit the implementation ofencode(to encoder: Encoder)
. – Nimbostratusnull
explicitly on them. And from my experience, is not a rare case... – Insomnolenceencode
. (The pieces of JSONEncoder you'd need to override arefileprivate
.) If it is non-trivial to implement, I would recommend SwiftGen to write it for you; this should be straightforward to build in SwiftGen. As a rule, it is not possible to get semi-custom Encodables. There are a small number of very specific configuration points, but beyond that, it's currently default or custom. I expect this to improve. – Fidelfidela