Swift泛型结构体数组JSON编码:UserChangeProto无法遵循Encodable的解决
报错根源
你碰到的Value of protocol type 'UserChangeProto' cannot conform to 'Encodable'是Swift目前明确的语法限制:协议本身只是类型蓝图,不是可直接用于编译期校验的具体类型,哪怕所有遵循该协议的实际类型都实现了Encodable,把异构的协议类型数组直接丢给JSONEncoder时,编译器没法自动推导序列化逻辑,必须手动补全多态集合的编码实现。
最少改动实现方案
完全不用重构你已经写好的枚举、泛型结构体,只需要加两段极短的代码就能解决问题:
给现有协议补一个编码能力的要求,让每个遵循协议的类型可以自己完成序列化:
protocol UserChangeProto { var op: ChangeOp { get } var path: ChangePath { get } // 新增这行 func encode(to encoder: Encoder) throws }你之前定义的
UserChange<ValueType: Encodable>本来就因为遵循Encodable自带了这个方法,不需要额外写实现,自动就满足协议要求。给元素是
UserChangeProto的数组补Encodable实现,让编码器能正常处理这类异构集合:extension Array: Encodable where Element == UserChangeProto { func encode(to encoder: Encoder) throws { var container = encoder.unkeyedContainer() try forEach { change in // 给每个元素单独分配编码上下文,避免多态类型信息丢失 try change.encode(to: container.superEncoder()) } } }
运行效果
你原来写的encodeChanges、requestUserChanges相关逻辑完全不用改,跑出来的序列化结果和接口要求的JSON格式完全对齐,不会再有编译报错:
[ { "op": "replace", "path": "/info/name", "value": "TestName" }, { "op": "replace", "path": "/info/number", "value": 100 }, { "op": "replace", "path": "/info/location", "value": ["STATE", "CITY"] }, { "op": "replace", "path": "/privacy/showLocation", "value": true } ]
这是目前场景下代码改动量最小的解法:你完全不需要写额外的
AnyUserChange类型擦除包装类,也不需要把所有value统一强转成Any再绕开类型检查,既保留了原有泛型结构体的类型安全,也没有额外的性能损耗。
内容的提问来源于stack exchange,提问作者rgajrawala
相关产品推荐
相关产品推荐

