Swift中构建GPT-4-Vision预览版POST请求JSON请求体问题
Swift Codable 适配多类型请求体内容
针对你需要构建包含文本和图片URL的GPT-4V请求体需求,以下两种方案可以解决现有Codable结构体的缺失问题:
方案一:枚举关联值(类型安全)
通过枚举关联值严格区分两种内容类型,避免无效的属性组合,同时实现Codable协议完成编码解码:
struct ImageInputRequestBody: Codable { let model: String = "gpt-4-vision-preview" let messages: [Message] let maxTokens: Int = 300 enum CodingKeys: String, CodingKey { case model, messages case maxTokens = "max_tokens" } struct Message: Codable { let role: String let content: [Content] } enum Content: Codable { case text(String) case imageURL(String) func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) switch self { case .text(let text): try container.encode("text", forKey: .type) try container.encode(text, forKey: .text) case .imageURL(let url): try container.encode("image_url", forKey: .type) try container.encode(ImageURLWrapper(url: url), forKey: .imageURL) } } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let type = try container.decode(String.self, forKey: .type) switch type { case "text": self = .text(try container.decode(String.self, forKey: .text)) case "image_url": let wrapper = try container.decode(ImageURLWrapper.self, forKey: .imageURL) self = .imageURL(wrapper.url) default: throw DecodingError.dataCorruptedError(forKey: .type, in: container, debugDescription: "未知内容类型:\(type)") } } enum CodingKeys: String, CodingKey { case type, text, imageURL = "image_url" } private struct ImageURLWrapper: Codable { let url: String } } }
使用示例
// 构建文本和图片内容 let textContent = ImageInputRequestBody.Content.text("动态传入的文本内容") let imageContent = ImageInputRequestBody.Content.imageURL("https://example.com/your-image.jpg") // 组装请求体 let message = ImageInputRequestBody.Message(role: "user", content: [textContent, imageContent]) let requestBody = ImageInputRequestBody(messages: [message]) // 编码为JSON Data用于POST请求 do { let jsonData = try JSONEncoder().encode(requestBody) // 将jsonData传入URLRequest的httpBody即可 } catch { print("编码失败:\(error)") }
方案二:结构体可选属性(简洁实现)
通过给Content结构体添加可选属性,配合便捷初始化方法快速构建不同类型的内容,实现成本更低:
struct ImageInputRequestBody: Codable { let model: String = "gpt-4-vision-preview" let messages: [Message] let maxTokens: Int = 300 enum CodingKeys: String, CodingKey { case model, messages case maxTokens = "max_tokens" } struct Message: Codable { let role: String let content: [Content] } struct Content: Codable { let type: String let text: String? let imageURL: ImageURL? enum CodingKeys: String, CodingKey { case type, text case imageURL = "image_url" } struct ImageURL: Codable { let url: String } // 便捷初始化方法,快速创建文本内容 static func text(_ text: String) -> Content { Content(type: "text", text: text, imageURL: nil) } // 便捷初始化方法,快速创建图片URL内容 static func imageURL(_ url: String) -> Content { Content(type: "image_url", text: nil, imageURL: ImageURL(url: url)) } } }
使用示例
let textContent = ImageInputRequestBody.Content.text("动态文本") let imageContent = ImageInputRequestBody.Content.imageURL("https://example.com/another-image.png") let message = ImageInputRequestBody.Message(role: "user", content: [textContent, imageContent]) let requestBody = ImageInputRequestBody(messages: [message]) do { let jsonData = try JSONEncoder().encode(requestBody) } catch { print("编码错误:\(error)") }
方案对比
- 枚举方案:类型安全,确保每个Content实例只能是一种类型,不会出现无效组合,适合需要严格校验的场景。
- 结构体方案:代码更简洁,实现速度快,适合快速开发,但需要注意不要错误地同时设置text和imageURL属性。
内容的提问来源于stack exchange,提问作者Vader20FF
相关产品推荐
相关产品推荐

