Swift中如何将WebSocket返回的JSON动态resource字段转为字符串?
Swift处理动态结构的WebSocket JSON数据
要解决WebSocket收到的JSON中resource结构随kind动态变化的问题,核心思路是先保留resource的原始数据,再根据kind字段解码为对应模型,同时可将原始数据转为字符串用于后续处理。具体步骤如下:
1. 定义Codable模型
先定义基础响应模型,固定字段(action、kind)直接映射,resource用Data类型存储以完整保留原始JSON结构:
import Foundation struct WebSocketResponse: Codable { let identifier: String let message: WebSocketMessage } struct WebSocketMessage: Codable { let action: String let kind: String let resource: Data // 存储原始JSON数据,适配任意结构 }
2. 解码WebSocket响应
解码时需设置JSONDecoder的dataDecodingStrategy为.deferredToData,让解码器自动将JSON对象转为Data:
// 假设jsonData是WebSocket收到的原始二进制数据 let jsonData: Data = ... let decoder = JSONDecoder() decoder.dataDecodingStrategy = .deferredToData // 若需要解析日期,可额外配置日期解码策略 decoder.dateDecodingStrategy = .iso8601 do { let response = try decoder.decode(WebSocketResponse.self, from: jsonData) // 获取固定字段值 let action = response.message.action let kind = response.message.kind // 将resource转为原始字符串格式 if let rawResourceString = String(data: response.message.resource, encoding: .utf8) { print("action = \"\(action)\"") print("kind = \"\(kind)\"") print("resource = \"\"\"\n\(rawResourceString)\n\"\"\"") } // 生成格式化的JSON字符串(更易读,和示例格式一致) if let jsonObject = try JSONSerialization.jsonObject(with: response.message.resource), let prettyData = try JSONSerialization.data(withJSONObject: jsonObject, options: .prettyPrinted), let prettyResourceString = String(data: prettyData, encoding: .utf8) { print("\n格式化后的resource:") print("resource = \"\"\"\n\(prettyResourceString)\n\"\"\"") } // 根据kind字段解码resource到对应业务模型 switch kind { case "Foo": let fooResource = try decoder.decode(FooResource.self, from: response.message.resource) // 执行replace等对应业务操作 print("处理Foo类型资源:\(fooResource.name)") case "Bar": let barResource = try decoder.decode(BarResource.self, from: response.message.resource) print("处理Bar类型资源:\(barResource)") default: print("未知资源类型:\(kind)") } } catch { print("解码错误:\(error.localizedDescription)") } // 示例:Foo类型对应的资源模型 struct FooResource: Codable { let ownerId: Int let name: String let id: Int let field1: String let fieldTwo: NestedObject let fieldXYZ: Int let createdAt: Date let updatedAt: Date // 映射JSON蛇形命名字段到Swift驼峰属性 enum CodingKeys: String, CodingKey { case ownerId = "owner_id" case name, id, field1 case fieldTwo = "fieldTwo" case fieldXYZ = "fieldXYZ" case createdAt = "created_at" case updatedAt = "updated_at" } } struct NestedObject: Codable { let name: String } // 示例:Bar类型对应的资源模型 struct BarResource: Codable { // 根据业务需求定义字段 }
3. 关键说明
- 用
Data存储resource是最优方案:既保留了原始JSON的完整性,又能直接复用JSONDecoder解码为对应模型,避免字符串转Data的额外开销。 - 若需要字符串格式,通过
String(data:encoding:)即可实现;要生成示例中的格式化多行字符串,使用JSONSerialization的.prettyPrinted选项即可。
内容的提问来源于stack exchange,提问作者Christoffer Reijer
相关产品推荐
相关产品推荐

