json.net - 为什么 Json.Net 6 不能将 T 反序列化为动态对象中的泛型列表? (适用于版本 5)

标签 json.net

我从 Json.net 的版本 5 更新到版本 6.0.8。但是,我的代码停止工作了,我花了一段时间才明白,在以前的版本中,它能够处理用列表实例化泛型类型的情况。但现在,它没有。我的问题是,是否需要调整任何设置才能获得旧行为?

在老图书馆,上课

 public class Result<T> 
    {
        public T Data
        {
            get;
            set;
        }

        public int ResultCode
        {
            get;
            set;
        }
    }

适用于用类似的东西实例化类的情况

Result<List<int>> result;

所以在我的代码中我做了类似的事情

dynamic result = JsonConvert.DeserializeObject(result, typeof(JObject));
int firstValue = (int)result.Data[0];

但是,对于最新的 Json.Net,它会失败并抛出异常(使用无效键值访问的 JObject 值:0。预期对象属性名称。)。我发现的唯一解决办法是

var resultList = result.Data.ToObject<List<int>>();
int firstValue = resultList[0];

显然,这种破坏动态的目的,我宁愿回到旧的行为。我能做些什么来告诉 Json.net T 可以是 List 吗?我看到它具有了解它的元数据,因为 $type 和 $values 属性在动态对象的结果 View 中可见。

感谢任何帮助,谢谢。

为了帮助隔离问题并回答评论问题,我创建了一个测试应用程序。事实证明,TypeNameHandling.All 选项是导致参数异常的原因。我在代码中添加了注释以显示好/坏的序列化。是的,我认为我们的代码中需要 All 选项。

    using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ShowingBug
{
    public class InterestingResult
    {
        public string Information { get; set; }
    }

    public class Result<T> 
    {
        public T Data { get; set; }
        public int ResultCode { get; set; }
    }


    class Program
    {
        static void Main(string[] args)
        {
            var veryInteresting = new List<InterestingResult>();
            veryInteresting.Add(new InterestingResult() { Information = "Good" });

            Result<List<InterestingResult>> operationResult = new Result<List<InterestingResult>>();
            operationResult.Data = veryInteresting;
            operationResult.ResultCode = 1;

            JsonSerializerSettings serializerSettings = new JsonSerializerSettings
            {
                TypeNameHandling = TypeNameHandling.Auto
            };

            var json = JsonConvert.SerializeObject(operationResult, serializerSettings);
            dynamic result = JObject.Parse(json);
            string information = (string)result.Data[0].Information;

            Console.Out.WriteLine(information);

            //The above works, however after some digging... 
            // I found that the option we use is not Auto, but All

            serializerSettings = new JsonSerializerSettings
            {
                TypeNameHandling = TypeNameHandling.All
            };

            json = JsonConvert.SerializeObject(operationResult, serializerSettings);
            result = JObject.Parse(json);

            // Now, you get an ArgumentException from Json.net 6.0.8 on the following line
            information = (string)result.Data[0].Information; 

            // It worked in previous version of Json.Net
            // I'm using .net 4.5.2 (if that makes a difference)
        }
    }
}

最佳答案

我在这里没有看到错误。问题是你似乎期待得到你原来的 Result<T>即使您指定反序列化对象类型应为 JObject,也返回对象.这永远行不通,因为 Result<T>不是 JObject , 和一个 JObject不能保存像 Result<T> 这样的自定义对象. JObject只能容纳 JProperty 的集合对象,那些只能保存从 JToken 派生的值.这是设计使然。

当您调用 JsonConvert.DeserializeObject(json, typeof(JObject)) 时,强制返回对象为 JObject , 即使接收变量声明为 dynamic .同样,JObject.Parse()将始终返回 JObject .

如果您想取回原始对象,尊重 JSON 中的嵌入式类型信息,您应该使用 JsonConvert.DeserializeObject() 的重载没有类型,传递相同的 JsonSerializationSettings你用来序列化的:

JsonSerializerSettings serializerSettings = new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.All
};

dynamic result = JsonConvert.DeserializeObject(json, serializerSettings);

关于json.net - 为什么 Json.Net 6 不能将 T 反序列化为动态对象中的泛型列表? (适用于版本 5),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30735129/

相关文章:

c# - 无法序列化 Azure ServiceBus 消息 - 从 'ExpiresAtUtc' 获取值时出错

c# - 使用自定义转换器从流中反序列化 Json

c# - 输入字符串不是有效数字 - JSON 反序列化

c# - 解析没有反射对象的复杂 JSON?

javascript - 当我使用 angularjs 从 MVC Controller 获取数据时,OwlCarousel 不工作

c# - 使用 JSON.NET 序列化/反序列化动态属性名称

c# - JSon.Net 如何让 $type 只用于反序列化

asp.net-mvc - MVC Web API 出现错误: 'ObjectContent` 1' 类型无法序列化响应正文,构造函数的参数数量不正确

c# - 如何将Jobject追加到Jproperty的Jarray中?

c# - 将属性映射到对象列表