System.Text.Json反序列化构造函数参数绑定异常的解决方法
问题描述
我定义了如下C#类:
public class BaseResponse { public bool Success { get; set; } public string Message { get; set; } public BaseResponse(bool success, string message) { Success = success; Message = message; } } public class TextToSpeechResponse : BaseResponse { [JsonPropertyName("audioPreviewSuccess")] public bool AudioPreviewSuccess { get; set; } [JsonPropertyName("result")] public SpeechSynthesisResult? Result { get; set; } [JsonPropertyName("errorMessage")] public string? ErrorMessage { get; set; } [JsonConstructor] public TextToSpeechResponse(bool audioPreviewSuccess, SpeechSynthesisResult speechResult, string? errorMessage, string message) : base(true, message) { AudioPreviewSuccess = audioPreviewSuccess; Result = speechResult; ErrorMessage = errorMessage; } public TextToSpeechResponse() : base(false, string.Empty) { AudioPreviewSuccess = false; Result = null; ErrorMessage = string.Empty; } }
尝试使用以下代码反序列化JSON:
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, }; return JsonSerializer.Deserialize<TextToSpeechResponse>(authorizedResponseBody, options) ?? new TextToSpeechResponse { Message = "Something went wrong with deserializing the authorizedResponseBody.", };
但抛出如下异常:
Each parameter in the deserialization constructor on type 'CpatCognitiveServicesApp.Responses.TextToSpeechResponse' must bind to an object property or field on deserialization. Each parameter name must match with a property or field on the object. Fields are only considered when 'JsonSerializerOptions.IncludeFields' is enabled. The match can be case-insensitive.
对应的JSON字符串:
{ "audioPreviewSuccess": true, "result": { "resultId": "ee80d3cf5f154fbba69401a4254b5b26", "reason": 9, "audioData": "UklGRnb1AABXQVZFZm10IBIAAAABAAEAgD4AAAB9AAACABAAAABkYXRhUPUAAAA", "properties": {} }, "errorMessage": null }
我曾误以为问题源于JSON中的properties字段为空对象{},尝试添加UnknownTypeHandling = JsonUnknownTypeHandling.JsonNode以及自定义类替换SpeechSynthesisResult,但异常仍未解决,请问如何成功反序列化?
问题分析
异常的核心原因是标记了[JsonConstructor]的构造函数参数绑定失败,和properties空对象无关:
- 构造函数中的
speechResult参数,与类中属性Result名称不匹配——System.Text.Json要求反序列化构造函数的参数名必须和类的属性/字段名一致(大小写不敏感),这里参数名speechResult和属性名Result不对应,无法绑定。 - 构造函数要求
message参数,但传入的JSON中没有对应的message字段,没有可绑定的数据源。
解决方案
方案一:修正JsonConstructor构造函数的参数
调整构造函数的参数名,使其与属性名匹配,并给message设置默认值(适配JSON中无该字段的情况):
[JsonConstructor] public TextToSpeechResponse(bool audioPreviewSuccess, SpeechSynthesisResult? result, string? errorMessage, string message = "") : base(true, message) { AudioPreviewSuccess = audioPreviewSuccess; Result = result; ErrorMessage = errorMessage; }
- 将
speechResult改为result,与属性Result名称一致,满足参数-属性绑定要求 - 给
message设置默认值"",确保JSON中无该字段时也能正常实例化
方案二:移除JsonConstructor特性
直接去掉[JsonConstructor],让System.Text.Json使用无参构造函数实例化对象,再自动赋值属性:
// 移除[JsonConstructor]特性 public TextToSpeechResponse(bool audioPreviewSuccess, SpeechSynthesisResult speechResult, string? errorMessage, string message) : base(true, message) { AudioPreviewSuccess = audioPreviewSuccess; Result = speechResult; ErrorMessage = errorMessage; }
这样反序列化流程会改为:调用无参构造函数创建对象 → 逐个匹配JSON字段赋值属性,避开构造函数参数绑定的问题。
额外处理:SpeechSynthesisResult的properties字段
如果SpeechSynthesisResult是第三方类,空对象{}仍导致问题,可通过以下方式处理:
- 修改序列化配置:
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, UnknownTypeHandling = JsonUnknownTypeHandling.JsonNode // 处理未知类型的空对象 };
- 自定义替代类:
public class CustomSpeechSynthesisResult { public string ResultId { get; set; } public int Reason { get; set; } public string AudioData { get; set; } public Dictionary<string, object> Properties { get; set; } = new(); }
然后将TextToSpeechResponse中的SpeechSynthesisResult? Result改为CustomSpeechSynthesisResult? Result。
内容的提问来源于stack exchange,提问作者PiousVenom
相关产品推荐
相关产品推荐

