如何使用 DeserializeObject 方法处理空值

End*_*cvs 5 c# json.net azureservicebus

我正在使用 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.

Run Code Online (Sandbox Code Playgroud)

原始 json 具有空值:

{
  "StartDate": null,
  "EndDate": null
}
Run Code Online (Sandbox Code Playgroud)

但我向 JsonConvert.DeserializeObject 提供设置以避免空值,如此处此处所述

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

知道为什么它一直抛出这个异常吗?

如果提供了实际的日期值,则代码运行良好。

有关代码的更多背景信息,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);
        }
    }
}

Run Code Online (Sandbox Code Playgroud)

Les*_*zur 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; }
}
Run Code Online (Sandbox Code Playgroud)

  • @Endovelicvs - 似乎“NullValueHandling.Ignore”不适用于构造函数参数,因为构造函数参数的值是构造和反序列化对象的“必需”。将构造函数参数声明为可为空可以解决该问题。或者,您可以创建一个带有可为空参数的私有构造函数,并用“[JsonConstructor]”标记它。 (3认同)
  • 我错过了构造函数 - 现在应该可以工作(适用于您的示例) (2认同)