微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

用JSONEncoders swift跳过空字符串

如何解决用JSONEncoders swift跳过空字符串

我是一个可编码序列化扩展,用于将可编码结构转换为字典,我面临的问题是字符串。我有时从UITextField中获取字符串值,但该值可能为空,因此会解码为空字符串。如果该值为空字符串,如何返回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 { $0 as? [String: Any] }
    }
}

如果我有结构

let example = Exa(age: 10,name: "")
let dict = example.requestDictionary
print(dict)

我希望它只打印["age": 10]并为空字符串返回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
   }
}

但是要实际跳过,您还需要为KeyedEncodingContainer.encode类型的SkipEmpty方法创建重载:

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 encode(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"

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。