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

为何Json.NET尝试反序列化我的仅获取(get-only)属性?

我懂你想要实现的是只序列化特定属性,但反序列化时跳过它的需求,结合你给出的代码片段,我来给你整理完整的可运行方案,分两种场景来说明:


场景1:属性本身是只读计算属性(你的示例情况)

你的Sup类里的yo属性是只读的计算属性(只有get访问器,没有set),Newtonsoft.Json(你代码里的Js...应该是指这个库)默认就会序列化它,但反序列化时不会尝试设置它——因为没有办法给它赋值。完整代码如下:

using Newtonsoft.Json;
using System;

public interface ISupYo { string Hi { get; } }
public class SupYo : ISupYo { public string Hi { get; } = "heya"; }

public interface ISup { int hiyo { get; } }
public class Sup : ISup 
{
    public Sup(int hiyo) { this.hiyo = hiyo; }
    public int hiyo { get; }

    // 只读计算属性,默认序列化输出,反序列化忽略
    public ISupYo yo => new SupYo();
}

class Program
{
    static void Main()
    {
        // 序列化
        var myNewSup = new Sup(42);
        var serializedJson = JsonConvert.SerializeObject(myNewSup, Formatting.Indented);
        Console.WriteLine("序列化结果:");
        Console.WriteLine(serializedJson);

        // 反序列化
        var deserializedSup = JsonConvert.DeserializeObject<Sup>(serializedJson, new JsonSerializerSettings
        {
            // 允许使用非无参构造函数创建实例
            ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
        });

        Console.WriteLine("\n反序列化后验证:");
        Console.WriteLine($"hiyo值:{deserializedSup.hiyo}");
        Console.WriteLine($"yo.Hi值:{deserializedSup.yo.Hi}"); // 输出heya,是新生成的实例,而非从JSON读取的
    }
}

运行后你会看到:序列化的JSON里包含yo字段,但反序列化时,yo属性是重新生成的SupYo实例,不会读取JSON里的对应值。


场景2:属性有setter,但仍要反序列化时忽略

如果以后你给yo属性加了set访问器,但还是想保持「序列化输出,反序列化忽略」的规则,可以用自定义ContractResolver来精确控制:

首先定义解析器:

public class SelectiveSerializeResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);
        
        // 指定只对Sup类的yo属性生效:序列化时包含,反序列化时跳过
        if (member.DeclaringType == typeof(Sup) && member.Name == nameof(Sup.yo))
        {
            property.Ignored = false; // 确保序列化时不被忽略
            property.ShouldDeserialize = _ => false; // 反序列化时直接跳过
        }
        
        return property;
    }
}

然后使用这个解析器进行序列化和反序列化:

var serializerSettings = new JsonSerializerSettings
{
    ContractResolver = new SelectiveSerializeResolver(),
    Formatting = Formatting.Indented,
    ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
};

// 序列化
var serialized = JsonConvert.SerializeObject(myNewSup, serializerSettings);

// 反序列化
var deserialized = JsonConvert.DeserializeObject<Sup>(serialized, serializerSettings);

这样不管yo属性有没有setter,都能严格实现「只序列化,不反序列化」的需求。


另外要注意:如果你的Sup类没有无参构造函数,反序列化时需要设置ConstructorHandling.AllowNonPublicDefaultConstructor,或者给类加一个私有的无参构造函数,否则Json.NET无法创建实例。

内容的提问来源于stack exchange,提问作者Gunnar Már Óttarsson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:46:02