json.net:DateTimeStringConverter在ReadJson()中获取一个已经由DateTime转换的对象

时间:2018-11-27 22:03:54

标签: c# datetime json.net deserialization

先决条件:

  • JSON.Net 11.0.2

我需要通过基于JSON的REST-API存储UTC DateTime往返日期/时间模式。

string utcTimestamp = DateTime.UtcNow.ToString( "o" );
// 2018-11-27T22:35:32.1234567Z

所以我给自己写了DateTimeStringConverter,以确保不涉及本地文化信息。

class DateTimeStringConverter:
    JsonConverter<DateTime>
{
    public override void WriteJson( JsonWriter writer, DateTime value, JsonSerializer serializer )
    {
        string convertedValue = value.ToString( "o" );
        writer.WriteValue( convertedValue );
    }

    public override DateTime ReadJson( JsonReader reader, Type objectType, DateTime existingValue, bool hasExistingValue, JsonSerializer serializer )
    {
        string value = reader.Value.ToString( );
        DateTime convertedValue = DateTime.Parse( value ).ToLocalTime( );
        return convertedValue;
    }
}

我对为什么没有毫秒就得到一个DateTime对象感到非常困惑。经过大量的反复试验后,我进入了。

public override DateTime ReadJson( JsonReader reader, Type objectType, DateTime existingValue, bool hasExistingValue, JsonSerializer serializer )
{
    Console.WriteLine( reader.Value.GetType( ).ToString( ) );
    // System.DateTime

    string value = reader.Value.ToString( );
    DateTime convertedValue = DateTime.Parse( value ).ToLocalTime( );
    return convertedValue;
}

JSON.Net为我提供了一个已经转换的DateTime对象,可以自行进行反序列化,而无需任何毫秒数据。我没有发现有关它是错误还是功能的任何线索。

为了反检查,我写了BooleanStringConverter

class BoolStringConverter:
    JsonConverter<bool>
{
    public override void WriteJson( JsonWriter writer, bool value, JsonSerializer serializer )
    {
        string convertedValue = false == value ? "False" : "True";
        writer.WriteValue( convertedValue );
    }

    public override bool ReadJson( JsonReader reader, Type objectType, bool existingValue, bool hasExistingValue, JsonSerializer serializer )
    {
        Console.WriteLine( reader.Value.GetType( ).ToString( ) );
        // System.String

        string value = ( string ) reader.Value;
        bool convertedValue = "False" == value ? false : true;
        return convertedValue;
    }
}

JSON.Net不能为我提供已转换的bool对象。

是错误还是功能?

2 个答案:

答案 0 :(得分:1)

这是Json.Net的已知行为。由于JSON没有用于表示日期的内置语法(就像布尔值一样),因此必须将其表示为字符串。默认情况下,Json.Net会尝试变得更好,并为您解析具有日期功能的字符串。

如果您使用自己的日期转换器,或者想要自己处理日期解析,则需要确保将None中的DateParseHandling设置为JsonSerializerSettings,否则内部阅读器将首先尝试处理它。

JsonSerializerSettings settings = new JsonSerializerSettings
{
    Converters = new List<JsonConverter> { new DateTimeStringConverter() },
    DateParseHandling = DateParseHandling.None
};

var foo = JsonConvert.DeserializeObject<Foo>(json, settings);

答案 1 :(得分:0)

我们可以将 DateTime 值直接转换为 DateTimeOffset,如下所示:(DateTimeOffset) reader.Value;.
完整代码:

public class DateTimeConverter : Newtonsoft.Json.JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(DateTimeOffset);
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.Value == null) return null;
            
            var deviceTime = (DateTimeOffset) reader.Value; 
            return deviceTime.DateTime;
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            writer.WriteValue((DateTime)value);
        }
    }