NSwag Studio生成C#客户端无法处理含数组的JSON请求体
问题:NSwag生成的C#客户端处理数组请求体时抛出反序列化异常
场景重现
使用NSwag Studio对接外部Swagger API生成C#客户端时,某API请求体包含类型化数组属性:
- Swagger规范(specification.json)中的定义:
"segmentValues": { "description": "The table >", "type": "array", "items": { "$ref": "#/definitions/DtoSegmentValue" } }
- 生成的Client.cs中该属性被正确识别为类型化集合:
/// <summary> /// The table > /// </summary> [Newtonsoft.Json.JsonProperty("segmentValues", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public System.Collections.Generic.ICollection<DtoSegmentValue> SegmentValues { get; set; }
但生成的API调用代码里,NSwag错误地将序列化后的JSON反序列化为Dictionary<string, string>,触发异常:
var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(update, _settings.Value); var dictionary_ = Newtonsoft.Json.JsonConvert.DeserializeObject<System.Collections.Generic.Dictionary<string, string>>(json_, _settings.Value); // 此行抛出异常 var content_ = new System.Net.Http.FormUrlEncodedContent(dictionary_);
异常信息:
Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: [. Path 'segmentValues', line 1, position 18. at Newtonsoft.Json.JsonTextReader.ReadStringValue(ReadType readType) at Newtonsoft.Json.JsonTextReader.ReadAsString() at Newtonsoft.Json.JsonReader.ReadForType(JsonContract contract, Boolean hasConverter)
原因分析
核心问题是NSwag误将该API的请求体格式识别为application/x-www-form-urlencoded,而非application/json。它先序列化对象为JSON,再尝试转成键值对字典构建表单编码内容,但数组类型无法转换为字符串类型的字典值,最终触发反序列化失败。
解决方法
方法1:强制指定请求内容类型(NSwag Studio配置)
- 打开NSwag Studio并加载目标Swagger规范。
- 切换到CSharp Client标签页,找到Advanced设置区。
- 将Default HTTP Content Type设置为
application/json。 - 检查Operation Settings中的单个API配置,确保未单独指定
application/x-www-form-urlencoded作为内容类型。 - 重新生成客户端代码,此时NSwag会直接发送序列化后的JSON请求体,不再尝试转换为字典。
方法2:手动修改生成的客户端代码(临时方案)
若配置调整无效,可临时修改Client.cs中对应API的代码,替换错误的字典转换逻辑:
将原代码:
var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(update, _settings.Value); var dictionary_ = Newtonsoft.Json.JsonConvert.DeserializeObject<System.Collections.Generic.Dictionary<string, string>>(json_, _settings.Value); var content_ = new System.Net.Http.FormUrlEncodedContent(dictionary_);
替换为:
var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(update, _settings.Value); var content_ = new StringContent(json_, System.Text.Encoding.UTF8, "application/json");
注意:手动修改的代码会在重新生成客户端时被覆盖,仅作为应急方案。
内容的提问来源于stack exchange,提问作者R. Reinders
相关产品推荐
相关产品推荐

