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

如何反序列化带in参数只读结构体构造函数的只读结构体?

解决Json.NET反序列化带in参数构造函数的readonly struct异常问题

这个问题我之前也碰到过!根源在于Json.NET(Newtonsoft.Json)的构造函数解析逻辑不支持处理带in/ref/out修饰符的参数。当你给Outer的构造函数用in Inner作为参数时,Json.NET会把这个参数的类型识别为Inner&(值类型的引用包装),而不是原本的Inner结构体类型,所以它找不到对应的构造函数来完成反序列化,就抛出了你看到的那个JsonSerializationException。

下面给两种解决方案,你可以根据自己的需求选择:

方案1:移除构造函数的in修饰符(最简单)

对于readonly struct来说,编译器已经会对传值操作做优化——尤其是小结构体,实际不会产生额外的副本(这也是readonly struct设计的优势之一)。所以直接去掉in修饰符,Json.NET就能正常识别构造函数了:

public readonly struct Outer
{
    [JsonConstructor]
    public Outer(Inner inner) => Inner = inner; // 移除in修饰符
    public Inner Inner { get; }
}

修改后重新运行你的代码,反序列化就能正常工作,同时也能保证结构体的不可变性。

方案2:自定义JsonConverter(保留in参数的场景)

如果你因为某些原因必须保留in参数的构造函数(比如你的Inner是非常大的结构体,确实需要避免副本),可以写一个自定义的JsonConverter来手动处理Outer的反序列化逻辑:

首先创建转换器类:

public class OuterConverter : JsonConverter<Outer>
{
    public override Outer ReadJson(JsonReader reader, Type objectType, Outer existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        // 先把JSON反序列化为Inner对象
        var inner = serializer.Deserialize<Inner>(reader);
        // 调用带in参数的构造函数创建Outer实例
        return new Outer(in inner);
    }

    public override void WriteJson(JsonWriter writer, Outer value, JsonSerializer serializer)
    {
        // 序列化逻辑直接复用默认行为即可
        serializer.Serialize(writer, new { value.Inner });
    }
}

然后在反序列化时指定这个转换器:

try
{
    var originalOuter = new Outer(new Inner(1));
    var json = JsonConvert.SerializeObject(originalOuter);
    
    // 添加转换器设置
    var settings = new JsonSerializerSettings();
    settings.Converters.Add(new OuterConverter());
    
    var newOuter = JsonConvert.DeserializeObject<Outer>(json, settings);
    Assert.IsTrue(originalOuter.Inner.I == newOuter.Inner.I);
    Console.WriteLine(json);
}
catch (Exception ex)
{
    Console.WriteLine("Failed with unhandled exception: ");
    Console.WriteLine(ex);
    throw;
}

这样就能绕过Json.NET对in参数的识别问题,手动完成反序列化流程。

内容的提问来源于stack exchange,提问作者Jeremy Morton

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:31:05