You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 8中如何将JSON反序列化到私有字段?

问题描述

通过阅读.NET 8序列化相关公告与文档,原本认为可以将JSON反序列化到私有字段,编写了如下代码:

public class User
{
    [JsonInclude]
    [JsonPropertyName("name")]
    private string _name = null!;
    
    public int Age { get; }
            
    [JsonConstructor]
    private User(string name, int age)
    {
        _name = name;
        Age = age;
    }
    
    private User(){}

}

// 反序列化代码
var userStr = @"{""name"": ""juan"", ""age"": 31}";
var options = new JsonSerializerOptions
{
    PropertyNameCaseInsensitive = true,
    IncludeFields = true,
    IgnoreReadOnlyFields = false
};
var user = JsonSerializer.Deserialize<User>(userStr, options)!;

运行后抛出异常:

Unhandled exception. System.InvalidOperationException: Each parameter in the deserialization constructor on type 'User' 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.
at System.Text.Json.ThrowHelper.ThrowInvalidOperationException_ConstructorParameterIncompleteBinding(Type parentType)...

将私有字段改为带getter的公共属性(如public string Name { get; })可以正常运行,但希望使用私有字段。实际场景中存在一个private List<T>,仅对外暴露public IReadOnlyCollection<T>的只读视图,询问是否可以让序列化程序使用私有字段。

解决方案

问题的核心是带[JsonConstructor]标记的构造函数参数,需要与类的字段/属性名称匹配(或通过特性显式映射),代码中构造函数参数name找不到对应名称的成员(字段是_name),因此抛出异常。以下两种方法可解决问题:

方法1:给构造函数参数添加[JsonPropertyName]特性

通过特性显式将构造函数参数与JSON字段名绑定,同时保留私有字段的[JsonInclude]特性,确保序列化器能识别私有字段:

public class User
{
    [JsonInclude]
    [JsonPropertyName("name")]
    private string _name = null!;
    
    public int Age { get; }
            
    [JsonConstructor]
    private User([JsonPropertyName("name")] string name, int age)
    {
        _name = name;
        Age = age;
    }
    
    private User(){}
}

方法2:修改构造函数参数名与私有字段名一致

将构造函数的name参数改为_name,让参数名直接匹配私有字段名,序列化器会自动完成绑定:

public class User
{
    [JsonInclude]
    [JsonPropertyName("name")]
    private string _name = null!;
    
    public int Age { get; }
            
    [JsonConstructor]
    private User(string _name, int age)
    {
        this._name = _name;
        Age = age;
    }
    
    private User(){}
}

针对私有集合的实际场景

对于私有List<T>字段+只读对外暴露的场景,同样可以用上述思路处理:

public class MyClass<T>
{
    [JsonInclude]
    [JsonPropertyName("items")]
    private List<T> _items = new();
    
    public IReadOnlyCollection<T> Items => _items.AsReadOnly();
    
    [JsonConstructor]
    private MyClass([JsonPropertyName("items")] List<T> items)
    {
        _items = items ?? new List<T>();
    }
    
    private MyClass(){}
}

配置后,序列化器会正确将JSON中的items数组反序列化到私有_items字段,对外仅暴露只读视图。


内容的提问来源于stack exchange,提问作者Juan Francisco Porto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 08:00:35