Swift Codable解析动态JSON后使用Array Map处理数据报错的问题咨询
解决Swift Codable枚举解析后的数据处理问题
嘿,刚接触Swift就敢用带关联值的枚举处理动态JSON,已经超棒了!咱们来拆解一下你遇到的问题,以及怎么优雅地解决它。
为啥会报错?
你写的Parse是带关联值的枚举,比如.listing(Listing)是枚举的一种“分支类型”,不是实例的属性。所以你直接写$0.listing或者model.listings.listing时,Swift会告诉你“不能把枚举case当实例成员用”——因为枚举实例本身可能是.listing、.t1、.t3中的任意一种,你得先判断它属于哪个分支,才能提取里面的关联值。
解决方法1:用compactMap + if case let提取目标类型
如果你想把[Parse]数组里所有的.listing类型元素提取出来,变成[Listing]数组,可以用compactMap结合模式匹配:
// 提取所有Listing类型的元素,自动过滤非listing的项 var test = model.listings.compactMap { parseItem in if case .listing(let listing) = parseItem { return listing } return nil }
这样test就是一个纯Listing数组,之后你就可以正常用map、filter等方法处理了。
解决方法2:单个元素的类型判断与提取
如果只是想访问数组中某个元素的关联值(比如第一个listing的children),可以这么写:
// 先判断第一个元素是不是listing类型,再提取关联值 if case .listing(let firstListing) = model.listings.first { let children = firstListing.children // children也是[Parse]类型,处理它的时候同样要用模式匹配 }
进阶优化:给枚举加便捷属性(让代码更简洁)
为了避免每次都写重复的模式匹配,你可以给Parse枚举加个扩展,添加几个计算属性来快速提取关联值:
extension Parse { // 快速获取当前实例的Listing(如果是listing类型的话) var listing: Listing? { if case .listing(let listing) = self { return listing } return nil } // 快速获取当前实例的Comment(不管是t1还是t3类型) var comment: Comment? { switch self { case .t1(let comment), .t3(let comment): return comment default: return nil } } // 同理可以添加more属性 var more: More? { if case .more(let more) = self { return more } return nil } }
有了这个扩展,你就可以像这样简洁地处理数据了:
// 提取所有Listing var test = model.listings.compactMap { $0.listing } // 访问第一个Listing的children if let firstListing = model.listings.first?.listing { let comments = firstListing.children.compactMap { $0.comment } // comments就是纯[Comment]数组,随便造作~ }
补充:处理嵌套的Parse数组
你的Listing里的children也是[Parse]类型,所以处理它的时候和顶层数组是一样的逻辑——用compactMap+模式匹配,或者用扩展里的便捷属性,就能把嵌套的动态类型转换成你需要的静态类型数组啦。
内容的提问来源于stack exchange,提问作者6pounder
相关产品推荐
相关产品推荐

