ไม่อยากได้ DateTime อยากได้แค่ string ทำไง? — How to ignore DateTime Deserializing in Newtonsoft Json.NET

คุณเคยประสบปัญหาในการ parse JSON string เป็น JObject แล้วได้ค่า DateTime format ที่ไม่พึงประสงค์หรือไม่???

อยากได้ string ธรรมดา แต่ Library Newtonsoft Json.NET ดันรู้มาก! แปลงเป็น DateTime ให้เฉยเลย แถมด้วย format ที่ไม่อยากได้ด้วย

วันนี้เรามีวิธีจัดการในส่วนตรงนี้ให้ สั้นๆง่ายๆ ไปดูกันเลย

เริ่มจากตอนที่เราต้องการจะแปลง JSON ไปเป็น JObject หรือ JToken โดยที่ JSON นั้นมี field บาง field ที่เป็นข้อมูลประเภท DateTime string ด้วย ตัวอย่างเช่น

{
"id": 51,
"name": "bamboo",
"realname": "Janista Tansiri",
"birthdate": "2002–09–03",
"created": "2019–11–16T15:48:52.245Z"
}

ซึ่งปกติ เวลาที่เราต้องการ Deserialize JSON ให้กลายเป็น JObject เราสามารถทำได้ 2 วิธีคือ ใช้ JsonConvert.DeSerializeObject<JObject>() หรือ JObject.Parse()

var joParsed = JObject.Parse(jsonstring);
var joDeserialized = JsonConvert.DeserializeObject<JObject>(jsonstring);

ทีนี้เวลาเราจะเอา value ไปใช้เราก็จะใช้คำสั่งพวกนี้

jobject[“key”]
jobject.GetValue(“key”)
jobject.Value<T>(“key”)

Console.WriteLine(joParsed["created"]);
Console.WriteLine(joParsed.GetValue("created"));
Console.WriteLine(joParsed.Value<object>("created"));
// 16-11-2019 3:48:52 PM
// 16-11-2019 3:48:52 PM
// 16-11-2019 3:48:52 PM
Console.WriteLine(joDeserialized["created"]);
Console.WriteLine(joDeserialized.GetValue("created"));
Console.WriteLine(joDeserialized.Value<object>("created"));
// 16-11-2019 3:48:52 PM
// 16-11-2019 3:48:52 PM
// 16-11-2019 3:48:52 PM

จังหวะนี้เราจะพบปัญหาตรงที่ เราจะได้ string ที่เป็น format ของวันที่ของเครื่องเราออกมา ซึ่งโดยตอนแรก เราตั้งใจไว้ว่ามันควรจะเป็น string แบบที่ส่งมาจาก JSON เลย ส่งอะไรมาได้แบบนั้น แต่ตอนนี้มันไม่ใช่

เรามาลอง ToString() กันดูก่อนว่าใช้ได้ไหม ผลก็คือ

Console.WriteLine(joParsed["created"].ToString());
Console.WriteLine(joParsed.GetValue("created").ToString());
Console.WriteLine(joParsed.Value<string>("created"));
// 16-11-2019 3:48:52 PM
// 16-11-2019 3:48:52 PM
// 11/16/2019 15:48:52
Console.WriteLine(joDeserialized["created"].ToString());
Console.WriteLine(joDeserialized.GetValue("created").ToString());
Console.WriteLine(joDeserialized.Value<string>("created"));
// 16-11-2019 3:48:52 PM
// 16-11-2019 3:48:52 PM
// 11/16/2019 15:48:52

ไปกันใหญ่เลย สรุปคือใช้ไม่ได้นั่นเอง

วิธีแก้ไข คือ

จังหวะที่เรา Deserialize ให้ใส่ JsonSerializerSettings ไปด้วย โดยตัว setting นี้จะมี field นึงที่ชื่อว่า DateTimeHandling เป็น enum ให้เราเลือกเป็น DateTimeHandling.None ซึ่งการตั้งค่านี้ จะทำให้ตัว Library ignore field ที่ดูแล้วว่าเป็น DateTime มันก็จะปล่อยผ่าน field นั้นไป มองเป็น string ธรรมดาแทน

var joDeserialized2 = JsonConvert.DeserializeObject<JObject>(jsonstring, new JsonSerializerSettings
{
DateParseHandling = DateParseHandling.None
});

สำหรับ JObject.Parse() จะไม่มี setting ในส่วนนี้ ทำให้เวลา parse จาก JSON มา ระบบจะมองเป็น DateTime อัตโนมัติเลย

แต่จะมีสำหรับ JObject.FromObject() ก็ใช้ JsonSerializer ได้เหมือนกัน

var model = new {
id = 51,
name = "bamboo",
realname = "Janista Tansiri",
birthdate = "2002-09-03",
created = "2019-11-16T15:48:52.245Z"
};
var joFromObject = JObject.FromObject(model, new JsonSerializer
{
DateParseHandling = DateParseHandling.None
});

เสร็จแล้วเราลอง get value ออกมา ก็จะได้ string ที่ตรงไปตรงมาแล้ว เย้!!

Console.WriteLine(joFromObject["created"]);
Console.WriteLine(joFromObject.GetValue("created"));
Console.WriteLine(joFromObject.Value<object>("created"));
// 2019-11-16T15:48:52.245Z
// 2019-11-16T15:48:52.245Z
// 2019-11-16T15:48:52.245Z
Console.WriteLine(joDeserialized2["created"]);
Console.WriteLine(joDeserialized2.GetValue("created"));
Console.WriteLine(joDeserialized2.Value<object>("created"));
// 2019-11-16T15:48:52.245Z
// 2019-11-16T15:48:52.245Z
// 2019-11-16T15:48:52.245Z
Console.WriteLine(joFromObject["created"].ToString());
Console.WriteLine(joFromObject.GetValue("created").ToString());
Console.WriteLine(joFromObject.Value<string>("created"));
// 2019-11-16T15:48:52.245Z
// 2019-11-16T15:48:52.245Z
// 2019-11-16T15:48:52.245Z
Console.WriteLine(joDeserialized2["created"].ToString());
Console.WriteLine(joDeserialized2.GetValue("created").ToString());
Console.WriteLine(joDeserialized2.Value<string>("created"));
// 2019-11-16T15:48:52.245Z
// 2019-11-16T15:48:52.245Z
// 2019-11-16T15:48:52.245Z

นอกจากนี้ ตัว JsonSerializerSettings ยังสามารถใส่ลูกเล่นได้อีกมากมาย เช่น Culture, DateTimeFormat, TimeZone ต่างๆ ไว้โอกาสหน้าอาจจะมาเล่าให้ฟังอีกครับ

var jsonSerializerSettings = new JsonSerializerSettings
{
DateParseHandling = DateParseHandling.DateTime,
DateFormatString = "dd/MM/yyyy HH:mm:ss",
Culture = new System.Globalization.CultureInfo("th-TH"),
DateTimeZoneHandling = DateTimeZoneHandling.Local
};

--

--

Aekasit Nakarad (IIwuDaFFK)
Arcadia Software Development

ติ่งเป็นงานหลัก devเป็นงานรอง ส่วนใหญ่จะ ITsupport เลี้ยงดู carry ให้เติบโต