使用 JSONEncoders 跳过空字符串 swift
Skipping empty string with JSONEncoders swift
我是一个 Codable 序列化扩展,我用它来将我的 Codable 结构转换为字典,我面临的问题是字符串。我有时会从 UITextField 中获取字符串值,该值可能为空,因此会解码一个空字符串。如果值为空字符串,我如何 return nil
extension Encodable {
var requestDictionary: [String: Any]? {
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
guard let data = try? encoder.encode(self) else { return nil }
return (try? JSONSerialization.jsonObject(with: data, options: .allowFragments)).flatMap { [=11=] as? [String: Any] }
}
}
如果我有一个结构
let example = Exa(age: 10, name: "")
let dict = example.requestDictionary
print(dict)
我希望它只为空字符串打印 ["age": 10]
和 return nil
我只是另一种方法,使用 属性 包装器来标记哪些属性可以被跳过。
@propertyWrapper
struct SkipEmpty {
var wrappedValue: String
}
extension SkipEmpty: Codable {
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
self.wrappedValue = try container.decode(String.self)
}
func encode(to encoder: Encoder) throws {
// nothing to do here, see below
}
}
但要真正跳过,您还需要为 SkipEmpty
类型的 KeyedEncodingContainer.encode
方法创建重载:
extension KeyedEncodingContainer {
mutating func encode(_ value: SkipEmpty, forKey key: K) throws {
if !value.wrappedValue.isEmpty {
try encode(value.wrappedValue, forKey: key) // encode the value here
}
}
}
您可以尝试使其更通用,例如SkipEmpty<T: Codable>
并为要跳过的值或谓词等提供另一个参数...
用法是:
struct Exa: Encodable {
var age: Int
@SkipEmpty var name: String
}
您可以实现自己的 String
编码方法扩展 KeyedEncodingContainer
:
extension KeyedEncodingContainer {
mutating func encode(_ value: String, forKey key: K) throws {
guard !value.isEmpty else { return }
try encodeIfPresent(value, forKey: key)
}
}
顺便说一句,您的请求字典可以简化为:
extension Encodable {
var dictionary: [String: Any]? {
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
return try? JSONSerialization.jsonObject(with: encoder.encode(self)) as? [String: Any]
}
}
游乐场测试:
struct Exa: Encodable {
let age: Int
let name: String
}
let example = Exa(age: 10, name: "")
let dict = example.dictionary!
print(dict) // "["age": 10]\n"
我是一个 Codable 序列化扩展,我用它来将我的 Codable 结构转换为字典,我面临的问题是字符串。我有时会从 UITextField 中获取字符串值,该值可能为空,因此会解码一个空字符串。如果值为空字符串,我如何 return nil
extension Encodable {
var requestDictionary: [String: Any]? {
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
guard let data = try? encoder.encode(self) else { return nil }
return (try? JSONSerialization.jsonObject(with: data, options: .allowFragments)).flatMap { [=11=] as? [String: Any] }
}
}
如果我有一个结构
let example = Exa(age: 10, name: "")
let dict = example.requestDictionary
print(dict)
我希望它只为空字符串打印 ["age": 10]
和 return nil
我只是另一种方法,使用 属性 包装器来标记哪些属性可以被跳过。
@propertyWrapper
struct SkipEmpty {
var wrappedValue: String
}
extension SkipEmpty: Codable {
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
self.wrappedValue = try container.decode(String.self)
}
func encode(to encoder: Encoder) throws {
// nothing to do here, see below
}
}
但要真正跳过,您还需要为 SkipEmpty
类型的 KeyedEncodingContainer.encode
方法创建重载:
extension KeyedEncodingContainer {
mutating func encode(_ value: SkipEmpty, forKey key: K) throws {
if !value.wrappedValue.isEmpty {
try encode(value.wrappedValue, forKey: key) // encode the value here
}
}
}
您可以尝试使其更通用,例如SkipEmpty<T: Codable>
并为要跳过的值或谓词等提供另一个参数...
用法是:
struct Exa: Encodable {
var age: Int
@SkipEmpty var name: String
}
您可以实现自己的 String
编码方法扩展 KeyedEncodingContainer
:
extension KeyedEncodingContainer {
mutating func encode(_ value: String, forKey key: K) throws {
guard !value.isEmpty else { return }
try encodeIfPresent(value, forKey: key)
}
}
顺便说一句,您的请求字典可以简化为:
extension Encodable {
var dictionary: [String: Any]? {
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
return try? JSONSerialization.jsonObject(with: encoder.encode(self)) as? [String: Any]
}
}
游乐场测试:
struct Exa: Encodable {
let age: Int
let name: String
}
let example = Exa(age: 10, name: "")
let dict = example.dictionary!
print(dict) // "["age": 10]\n"