首页 > 解决方案 > 如何序列化任务使用 Json.NET?

问题描述

考虑

public class InQuestion<TType>
{
    // JsonConverter(typeof CustomConverter))
    public Task<TType> toConvert { get; set; }
}

如何使用 json.net (反)序列化此类?

我想我真正想要序列化的是底层的Task<T>.Result,然后可以用Task<T>.FromResult()反序列化。如果我要使用自定义 JsonConverter,我无法通过 Attribute 传递通用 TType,以在 JsonConverter 中重构(或检索)TType 对象。因此我被困住了。

问题来自这段代码:

public class Program
{
    public class InQuestion<TType>
    {
        public Task<TType> toConvert { get; set; }
    }

    public class Result
    {
        public int value { get; set; }
    }

    public static async Task Main()
    {
        var questionable = new InQuestion<Result>();
        questionable.toConvert = Task.Run(async () => new Result { value = 42 });
        await questionable.toConvert; 

        string json = JsonConvert.SerializeObject(questionable);
        Debug.WriteLine(json); 
        InQuestion<Result> back = JsonConvert.DeserializeObject(json, typeof(InQuestion<Result>)) as InQuestion<Result>;
        Debug.Assert(back?.toConvert?.Result?.value == 42); 
    }
}

令我惊讶的是,它在调用 JsonConvert.DeserializeObject 期间停止了。https://github.com/JamesNK/Newtonsoft.Json/issues/1886讨论了这个问题并建议合理的“不要序列化/反序列化任务。”,但实际上并没有建议如何序列化底层任务< T >.结果。

标签: c#jsonserializationjson.nettask

解决方案


ATask是对未来值的承诺,当然您不能序列化尚未提供的值。

因为InQuestion对象包含一个Task成员,所以您不能序列化和反序列化该InQuestion对象。

解决方法是将结果序列化,并在反序列化后重建InQuestion对象。

public static async Task Main()
{
    var questionable = new InQuestion<Result>();
    questionable.toConvert = Task.Run(async () => new Result { value = 42 });

    Result result = await questionable.toConvert;
    string json = JsonConvert.SerializeObject(result);
    
    Result back = JsonConvert.DeserializeObject(json, typeof<Result>) as Result;

    InQuestion<Result> reconstructed = new InQuestion<Result>()
    {
        toConvert = Task.FromResult(back)
    };
}

推荐阅读