如何使用 DeserializeObject 方法处理空值

5
我正在使用Newtonsoft.Json反序列化一个对象,并且我遇到了以下异常:
Newtonsoft.Json.JsonSerializationException
  HResult=0x80131500
  Message=Error converting value {null} to type 'System.DateTime'. Path 'StartDate', line 1, position 62.
  Source=Newtonsoft.Json
  
Inner Exception 1:
InvalidCastException: Null object cannot be converted to a value type.

原始 JSON 中存在空值:

{
  "StartDate": null,
  "EndDate": null
}

但是我正在向JsonConvert.DeserializeObject提供设置,以避免空值,如这里这里所述:

var convertedMessage = JsonConvert.DeserializeObject<T>(
                Encoding.UTF8.GetString(message.Body),
                new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });

你有什么想法,为什么它一直抛出这个异常?

如果提供实际的日期值,代码就会运行得很好。

更多关于代码的背景信息,message.Body 是通过服务总线(Microsoft.Azure.ServiceBus.Message 类)接收到的消息体。并且将 GetString 方法应用于它将返回与发送的消息相同的字符串。

代码可运行示例:

using System;
using System.Text;
using Microsoft.Azure.ServiceBus;
using Newtonsoft.Json;


namespace ConsoleApp1
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine(DeserializeJsonMessage<SampleMessage>(
                new Message(Encoding.UTF8.GetBytes("{\"Id\":\"d2725a22-fdfb-48df-8871-54bbcb1a95b4\",\"StartDate\":null,\"EndDate\":null}"))
                ));
        }

        public static T DeserializeJsonMessage<T>(Message message) where T : IMessage
        {
            var convertedMessage = JsonConvert.DeserializeObject<T>(
                Encoding.UTF8.GetString(message.Body),
                new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });

            return convertedMessage;
        }
    }

    public interface IMessage
    {
        Guid Id { get; set; }
        DateTime StartDate { get; set; }
        DateTime EndDate { get; set; }
    }

    public class SampleMessage : IMessage
    {
        public Guid Id { get; set; }
        public DateTime StartDate { get; set; }
        public DateTime EndDate { get; set; }

        public SampleMessage(Guid id, DateTime startDate, DateTime endDate)
        {
            Id = id;
            StartDate = startDate;
            EndDate = endDate;
        }

        public override string ToString()
        {
            return JsonConvert.SerializeObject(this);
        }
    }
}

1个回答

3

你是否尝试将开始/结束日期设置为可空对象,并通过它们实现一个接口?

public class SampleMessage : IMessage
{
    public Guid Id { get; set; }
    public DateTime? StartDate { get; set; }
    public DateTime? EndDate { get; set; }

    public SampleMessage(Guid id, DateTime? startDate, DateTime? endDate)
    {
        Id = id;
        StartDate = startDate;
        EndDate = endDate;
    }

    public override string ToString()
    {
        return JsonConvert.SerializeObject(this);
    }

    DateTime IMessage.StartDate { get => this.StartDate ?? DateTime.Now; set => this.StartDate = value; }
    DateTime IMessage.EndDate { get => this.EndDate ?? DateTime.Now; set => this.EndDate = value; }
}

之前尝试过了,代码抛出了相同的异常。 - Endovelicvs
2
我错过了构造函数 - 现在应该可以工作了(在您的示例上有效) - Leszek Mazur
1
不错!谢谢。我忘记了我还需要更新构造函数。但是,为什么JsonSerializer设置(NullValueHandling.Ignore)没有起作用呢? - Endovelicvs
我建议使用default(DateTime)来表示未初始化的值,而不是DateTime.Now - dbc
3
似乎 NullValueHandling.Ignore 不适用于构造函数参数,因为需要一个值来构造和反序列化对象。将构造函数参数声明为可空类型可以解决这个问题。或者你可以创建一个带有可空参数的私有构造函数,并将其标记为 [JsonConstructor] - dbc

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