Newtonsoft.Json.Linq.JObject.ToObject() 以字符串格式转换日期

Posted

技术标签:

【中文标题】Newtonsoft.Json.Linq.JObject.ToObject() 以字符串格式转换日期【英文标题】:Newtonsoft.Json.Linq.JObject.ToObject() converting date in string format 【发布时间】:2018-06-14 13:00:42 【问题描述】:

我正在构建一个 .net 核心库。该错误适用于 1.1 和 2.0。

我有一个JObject(我阅读了许多其他答案,人们告诉 OP 只做JsonConvert.Deserialize(obj),这不是一个选项,我需要它)。

JObject 在字符串中有一个日期,我将把它反序列化为一个也有它作为字符串的对象,并且我需要它的格式与提供的相同。

一个answer 我看到声称一旦对象变为JObject,日期就会被解析为该格式,但我发现事实并非如此,.ToObject() 是实际发生这种转换的地方。

我在这里搜索了很多,发现了一些对我不起作用的公认解决方案。

    Setting DateParseHandling.None Explicitly specifying the date format.(tried the other approach in this answer as well)

这些都不起作用。

测试代码:

using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace JobjectDateTest

    class Program
    
        static void Main(string[] args)
        
            var json = @"""Data"": ""CreatedAt"":""2018-01-04T14:48:39.7472110Z""";
            var thing = JsonConvert.DeserializeObject<Thing>(json);
            Console.WriteLine(thing.Data.First); // "CreatedAt": "2018-01-04T14:48:39.747211Z"

            var jsonSer = new JsonSerializer  DateFormatString = "yyyy-MM-ddTHH:mm:ssZ" ;
            var innerThing = thing.Data.ToObject<InnerThing>(jsonSer);

            Console.WriteLine(innerThing.CreatedAt); // 01/04/2018 14:48:39
            Console.WriteLine(innerThing.CreatedAt == "2018-01-04T14:48:39.7472110Z"); // false

            jsonSer = new JsonSerializer  DateParseHandling = DateParseHandling.None ;
            innerThing = thing.Data.ToObject<InnerThing>(jsonSer);

            Console.WriteLine(innerThing.CreatedAt); // 01/04/2018 14:48:39
            Console.WriteLine(innerThing.CreatedAt == "2018-01-04T14:48:39.7472110Z"); // false
        

        class Thing
        
            public JObject Data  get; set; 
        

        class InnerThing
        
            public string CreatedAt  get; set; 
        
    

【问题讨论】:

有什么理由不使用innerThing = JsonConvert.DeserializeObject&lt;InnerThing&gt;(thing.Data.ToString()); 【参考方案1】:

您一直在尝试序列化数据,但是当您反序列化 JSON 开始时,转换正在发生。这就是您需要禁用DateParseHandling 的地方。这是您需要的更改:

var settings = new JsonSerializerSettings  DateParseHandling = DateParseHandling.None ;
var thing = JsonConvert.DeserializeObject<Thing>(json, settings);

新输出:

"CreatedAt": "2018-01-04T14:48:39.7472110Z"
2018-01-04T14:48:39.7472110Z
True
2018-01-04T14:48:39.7472110Z
True

你可以通过这种方式看到JObject的区别:

var property = (JProperty) thing.Data.First;
var value = (JValue) property.Value;
Console.WriteLine(value.Type);

在指定设置之前,这将打印Date。使用阻止日期解析的设置,这将打印String

【讨论】:

【参考方案2】:

我遇到了类似的问题,解决了

JToken rootObj = JsonConvert.DeserializeObject&lt;dynamic&gt;(myJsonString, new JsonSerializerSettings DateParseHandling = DateParseHandling.None ) as JToken;

正如其他人所写,一旦您拥有JObject / JToken,对于DateParseHandling 已经为时已晚,并且DateParseHandling 不适用于JToken.Parse()

JToken rootObj = JsonConvert.DeserializeObject<dynamic>(myJsonString, new JsonSerializerSettings  DateParseHandling = DateParseHandling.None ) as JToken;
if (rootObj.Children<JProperty>().Count() != 1) Console.WriteLine($"Error: json no or multiple root tokens");
JProperty rootProp = rootObj.Children<JProperty>().First(); // with the property you can access the name if needed
if (rootProp.Name.Equals("theTokenNameIAmLookingFor"))
   
      Console.WriteLine($"found my token name: rootProp.Name");
      MyClass myObj = rootObj.ToObject<MyClass>();
   

【讨论】:

以上是关于Newtonsoft.Json.Linq.JObject.ToObject() 以字符串格式转换日期的主要内容,如果未能解决你的问题,请参考以下文章