Swift 4中使用JSONDecoder将nil转为空字符串的实现方案
嘿,这个问题我刚好处理过,给你两个最简的解决方案,都是在解码阶段完成转换,完全匹配你的需求:
方案一:自定义解码初始化方法(适合单个结构体少量字段)
直接在Customer结构体里实现Codable的自定义解码逻辑,把JSON中的null直接转换成空字符串:
struct Customer: Codable { var id: Int! var cnum: String! var cname: String! init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) // 解码id(假设JSON中id不会为null,若有可能也可以用decodeIfPresent处理) id = try container.decode(Int.self, forKey: .id) // 处理cnum:若JSON中为null则转为空字符串 cnum = try container.decodeIfPresent(String.self, forKey: .cnum) ?? "" // 处理cname:同理转换null为空字符串 cname = try container.decodeIfPresent(String.self, forKey: .cname) ?? "" } // 如果需要编码(把结构体转回JSON),可以添加下面的方法,否则可忽略 func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(id, forKey: .id) try container.encode(cnum, forKey: .cnum) try container.encode(cname, forKey: .cname) } private enum CodingKeys: String, CodingKey { case id, cnum, cname } }
这个方法的核心是用decodeIfPresent替代decode:前者遇到JSON中的null会返回nil,我们再用?? ""把nil替换成空字符串,这样你的隐式解包字段永远不会是nil,完全符合你“字段不可设为可选类型”的要求。
方案二:使用属性包装器(适合多个字段/结构体复用)
如果你的项目中有很多类似需要把null转空字符串的字段,用属性包装器可以统一处理逻辑,避免重复代码:
// 定义一个属性包装器,专门处理null转空字符串 @propertyWrapper struct NonEmptyString: Codable { var wrappedValue: String init(wrappedValue: String) { self.wrappedValue = wrappedValue } init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() wrappedValue = try container.decodeIfPresent(String.self) ?? "" } } // 修改Customer结构体,给需要处理的字段加上标记 struct Customer: Codable { var id: Int! @NonEmptyString var cnum: String! @NonEmptyString var cname: String! }
之后只要给需要转换的字符串字段加上@NonEmptyString标记,解码时就会自动把null转成空字符串,后续其他结构体也能直接复用这个包装器,非常省心。
关键说明
这两个方案都是在解码阶段完成转换,不需要额外遍历解码后的数组做二次处理,是最直接高效的方式,而且完美满足你“字段不可设为可选类型”的要求。
内容的提问来源于stack exchange,提问作者Robert Smith
相关产品推荐
相关产品推荐

