JSON反序列化,错误:将null转换为值类型,如何知道导致错误的确切属性?

8
在我的C#代码中,我试图反序列化一个具有数百个属性(复杂的、基本的和派生的)的JSON,并且我遇到了一个错误Cannot convert null to a value type. 虽然最终通过手动故障排除我知道了哪个属性引起了问题。
但是,是否有一种简单的方法可以知道JSON或Result_TYPE 属性或属性(一次性),导致了这个问题?
我尝试查看异常的详细窗口,但我只能知道数据类型。在我的情况下,它是null试图转换为boolean,但找不到属性名称。
例如:我的JSON
  {
      "customerData": 
      {
        //... other json data

        "someClass":{
            "someClassProp1":"prop1Value",
            "someClassProp2":"prop2Value"
           },
        "isExistData":null,
        "someOtherClass":null

        //... some other json data
      }
  }

并且Result_TYPE是:

Public class CustomerData
{
    // Other properties

    public SomeClass someClass:
    public bool isExistData;    
    public SomeOtherClass someOtherClass:

    // some Other properties
}

我正在使用JavaScriptSerializer().Deserialize<T>(jsonString);。在上面的例子中,我怎么知道属性isExistData会导致反序列化错误,因为属性类型是boolean而传入的数据是null。[当然,除了手动调试外,可能还有数百个属性]。是否有更好的方法来定位确切的属性?

isExistData 是一个值类型,不能为 null... - Daniel A. White
你可以考虑将值类型设为可空的... - Daniel A. White
@DanielA.White:是的,我知道 : ) ,已经解决了我的问题,但是很好奇是否有任何可以在运行时定位的序列化程序/反序列化程序? - anoop
json.net 有很多选项。 - Daniel A. White
请问我应该使用JavaScriptSerializer或其他哪个选项,在运行时定位有问题的属性? - anoop
1个回答

7
如果您不介意使用其他序列化程序,那么只需使用JSON .NET即可。它允许您在反序列化时出现错误时运行自定义代码:
var errors = new List<string>();
var data = JsonConvert.DeserializeObject<CustomerData>(jsonString,
    new JsonSerializerSettings
    {
        NullValueHandling = NullValueHandling.Include,
        Error = delegate (object sender, Newtonsoft.Json.Serialization.ErrorEventArgs earg)
         {
             errors.Add(earg.ErrorContext.Member.ToString());
             earg.ErrorContext.Handled = true;
         }
    });

在错误中,您将获得所有有问题的属性。当然,默认情况下,JSON.NET不会在空属性上失败,这就是为什么我设置了JsonSerializerSettings的NullValueHandling属性。您可以在文档中阅读更多信息:http://www.newtonsoft.com/json/help/html/SerializationErrorHandling.htm 如果由于任何原因您必须继续使用JavaScriptSerializer,则只需将对象反序列化为动态对象 (将JSON反序列化为C#动态对象?),然后检查任何值类型属性是否具有空值即可。
foreach (var property in typeof(CustomerData).GetProperties().Where(p => p.PropertyType.IsValueType))
{
    if (dynamicsData[property.Name] == null)
    {
        Console.WriteLine($"This is problematic property: {property.Name}");
    }
}

谢谢您的回复,但我想定位仅映射到非空类型的特定属性。如果没有办法定位,那么在大型应用程序中手动调试会很痛苦。 - anoop
不确定你是否理解了我的回答,它展示了你刚才所描述的内容... - Pawel Gradecki
我稍微修改了答案,使其更易理解,并反映了你在问题中的更改。 - Pawel Gradecki
谢谢你,我收到了你的答案,你的代码片段也给出了引起属性错误的原因,我也尝试过使用反射来解决问题。但是我很好奇,是否有任何可以在运行时定位的序列化程序/反序列化程序?而不需要编写任何代码片段。 - anoop
好的,看来我需要使用Json.Net,它似乎与我所需的相似。谢谢。 - anoop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接