Swift Codable枚举编码成功但解码失败问题求助
问题描述
我通过嵌套Codable类型定义了GeoJSONFeatureGeometryCoordinates枚举,用于解码GeoJSON文件中的点、多边形与多多边形。解码GeoJSON文件时一切正常,但将该数据编码为二进制数据存储到Core Data后,再次解码却失败,抛出typeMismatch错误。
枚举代码
enum GeoJSONFeatureGeometryCoordinates: Codable { case point([Double]) case polygon([[[Double]]]) case multipolygon([[[[Double]]]]) init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() do { let polygonVal = try container.decode([[[Double]]].self) self = .polygon(polygonVal) } catch DecodingError.typeMismatch { do { let multipolygonVal = try container.decode([[[[Double]]]].self) self = .multipolygon(multipolygonVal) } catch DecodingError.typeMismatch { let pointVal = try container.decode([Double].self) self = .point(pointVal) } } } }
测试代码
do { let encoder = JSONEncoder() let encodedCoordinates = try encoder.encode(centroid.geometry.coordinates) let decoder = JSONDecoder() let decodedCoordinates = try decoder.decode(GeoJSONFeatureGeometryCoordinates.self, from: encodedCoordinates) } catch { fatalError("\n\n Error archiving feature.geometry.coordinates as Data") }
解决方案
问题出在你只手动实现了解码逻辑init(from:),但没有实现对应的编码逻辑encode(to:)。Codable自动合成的编码逻辑无法正确处理这种嵌套数组类型的枚举,导致编码后的数据格式和解码时预期的单一值容器不匹配,最终触发typeMismatch错误。
需要手动添加encode(to:)方法,根据枚举的case类型将对应的数据编码到单一值容器中:
enum GeoJSONFeatureGeometryCoordinates: Codable { case point([Double]) case polygon([[[Double]]]) case multipolygon([[[[Double]]]]) init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() do { let polygonVal = try container.decode([[[Double]]].self) self = .polygon(polygonVal) } catch DecodingError.typeMismatch { do { let multipolygonVal = try container.decode([[[[Double]]]].self) self = .multipolygon(multipolygonVal) } catch DecodingError.typeMismatch { let pointVal = try container.decode([Double].self) self = .point(pointVal) } } } func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() switch self { case .point(let value): try container.encode(value) case .polygon(let value): try container.encode(value) case .multipolygon(let value): try container.encode(value) } } }
添加这个方法后,编码时会将每个枚举case对应的数据以单一数组的形式写入,和解码时的读取逻辑完全匹配,二次解码就能正常完成。
内容的提问来源于stack exchange,提问作者whaleshark
相关产品推荐
相关产品推荐

