You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 14:22:45