C#动态自定义对象JSON序列化问题:适配OpenAI Assistant API函数调用
解决方案
针对编译时无法确定动态参数数量、需要序列化符合OpenAI Assistant API格式的JSON问题,以下是两种可行的实现方案:
方案1:System.Text.Json 原生支持(推荐)
利用[JsonExtensionData]特性自动处理动态属性,无需自定义序列化逻辑:
重构FunctionCall类
using System.Text.Json.Serialization; public class FunctionCall { public string x { get; set; } public int y { get; set; } // 存储动态参数:键为参数名(如"location"),值为参数Schema对象 [JsonExtensionData] public Dictionary<string, object> DynamicParameters { get; set; } = new(); }
实例构建与序列化
using System.Text.Json; // 定义参数Schema(可改用强类型类替代匿名对象) var locationSchema = new { type = "string", description = "The city and state e.g. San Francisco, CA" }; var unitSchema = new { type = "string", @enum = new[] { "c", "f" } }; // 创建FunctionCall实例 var functionCall = new FunctionCall { x = "sample_x", y = 456, DynamicParameters = new() { { "location", locationSchema }, { "unit", unitSchema } } }; // 序列化生成符合要求的JSON var json = JsonSerializer.Serialize(functionCall, new JsonSerializerOptions { WriteIndented = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
序列化后,DynamicParameters中的键值对会自动展开为顶级属性,完美匹配OpenAI要求的parameters.properties结构。反序列化时,动态属性会自动被解析到DynamicParameters字典中。
方案2:Newtonsoft.Json 动态处理
通过JObject合并固定属性与动态参数:
重构FunctionCall类
using Newtonsoft.Json.Linq; public class FunctionCall { public string x { get; set; } public int y { get; set; } public JObject DynamicParameters { get; set; } = new(); }
实例构建与序列化
using Newtonsoft.Json; var functionCall = new FunctionCall { x = "sample_x", y = 456 }; // 添加动态参数Schema functionCall.DynamicParameters["location"] = JObject.FromObject(new { type = "string", description = "The city and state e.g. San Francisco, CA" }); functionCall.DynamicParameters["unit"] = JObject.FromObject(new { type = "string", @enum = new[] { "c", "f" } }); // 合并固定属性与动态参数 var fixedJson = JObject.FromObject(functionCall); fixedJson.Remove(nameof(FunctionCall.DynamicParameters)); fixedJson.Merge(functionCall.DynamicParameters); // 生成最终JSON var json = fixedJson.ToString(Formatting.Indented);
额外优化建议
如果需要类型安全,可定义ParameterSchema强类型类替代匿名对象:
public class ParameterSchema { public string Type { get; set; } public string Description { get; set; } public string[] Enum { get; set; } }
内容的提问来源于stack exchange,提问作者Sergio B.
相关产品推荐
相关产品推荐

