将JSON反序列化为C# List时触发System.InvalidOperationException异常
定义的C#类:
public class Record { public string Name { get; set; } // Flat owner public int Size { get; set; } // Flat size public int Enterance { get; set; } // Enterance number [JsonConstructor] public Record([JsonPropertyName("Name")] string name, [JsonPropertyName("Size")] int size, [JsonPropertyName("Enterance")] int ent) { this.Name = name; this.Size = size; this.Enterance = ent; } }
序列化后得到的JSON:
[ { "Name": "Majitel", "Size": 100, "Enterance": 1 } ]
反序列化代码:
string json = File.ReadAllText(filepath).Trim(); var records = JsonSerializer.DeserializeObject<List<Record>>(json);
抛出的异常:
System.InvalidOperationException: Each parameter in the deserialization constructor on type '<project_name>.Record' 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.
错误原因分析
异常核心问题是反序列化构造函数的第三个参数名ent与类中Enterance属性名不匹配。
System.Text.Json使用标记[JsonConstructor]的构造函数时,要求每个参数满足两个条件:
- 能通过
[JsonPropertyName]或参数名匹配JSON键(这一点已满足); - 参数名必须与类的属性/字段名对应(大小写不敏感,但名称需足够匹配)。
参数ent和属性Enterance完全不匹配,序列化器无法识别该参数对应哪个属性,因此抛出绑定异常。
解决方法
方案一:修改构造函数参数名,与属性名匹配
将第三个参数名改为enterance(与属性名一致,大小写不敏感),序列化器即可自动绑定到Enterance属性:
public class Record { public string Name { get; set; } // Flat owner public int Size { get; set; } // Flat size public int Enterance { get; set; } // Enterance number [JsonConstructor] public Record([JsonPropertyName("Name")] string name, [JsonPropertyName("Size")] int size, [JsonPropertyName("Enterance")] int enterance) { this.Name = name; this.Size = size; this.Enterance = enterance; } }
方案二:简化构造函数,利用默认匹配逻辑
由于JSON键和类属性名已经一致,可直接去掉[JsonPropertyName],仅保证参数名与属性名匹配(大小写不敏感):
[JsonConstructor] public Record(string name, int size, int enterance) { this.Name = name; this.Size = size; this.Enterance = enterance; }
方案三:移除自定义构造函数,添加无参构造
如果不需要自定义构造逻辑,可移除标记[JsonConstructor]的构造函数,添加无参构造函数,让序列化器使用默认属性赋值逻辑:
public class Record { public string Name { get; set; } // Flat owner public int Size { get; set; } // Flat size public int Enterance { get; set; } // Enterance number // 新增无参构造函数 public Record() {} }
内容的提问来源于stack exchange,提问作者Jayne

