2014-12-05 376 views
2

只將JSON日期時間值轉換爲零(例如「0000-00-00 00:00:00」)不能使用標準的Json.net IsoDateTimeConverter。我開發了一個保存此值DateTime.MinValue的自定義轉換器。另外一個DateTime.MinValue將被寫爲「ZeroDateString」。所有其他字符串都由基本IsoDateTimeConverter類處理。 我使用此轉換器JsonNet註釋日期時間屬性。將JSON日期時間值轉換爲零值的最佳方法(例如「0000-00-00 00:00:00」)

有沒有更好,更簡單的方法來處理這個問題,例如在基礎層面上,哪裏不需要註釋?

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Text.RegularExpressions; 
using System.Threading.Tasks; 
using Newtonsoft.Json; 

namespace DataLayer 
{ 
    /// <summary> 
    /// Custom IsoDateTimeConverter for DateTime strings with zeros. 
    /// 
    /// Usage Sample 
    /// [JsonConverter(typeof(ZerosIsoDateTimeConverter), "yyyy-MM-dd hh:mm:ss", "0000-00-00 00:00:00")] 
    /// public DateTime Zerodate { get; set; } 

    /// </summary> 
    public class ZerosIsoDateTimeConverter : Newtonsoft.Json.Converters.IsoDateTimeConverter 
    { 
     /// <summary> 
     /// The string representing a datetime value with zeros. E.g. "0000-00-00 00:00:00" 
     /// </summary> 
     private readonly string _zeroDateString; 

     /// <summary> 
     /// Initializes a new instance of the <see cref="ZerosIsoDateTimeConverter"/> class. 
     /// </summary> 
     /// <param name="dateTimeFormat">The date time format.</param> 
     /// <param name="zeroDateString">The zero date string. 
     /// Please be aware that this string should match the date time format.</param> 
     public ZerosIsoDateTimeConverter(string dateTimeFormat, string zeroDateString) 
     { 
      DateTimeFormat = dateTimeFormat; 
      _zeroDateString = zeroDateString; 
     } 

     /// <summary> 
     /// Writes the JSON representation of the object. 
     /// If a DateTime value is DateTime.MinValue than the zeroDateString will be set as output value. 
     /// </summary> 
     /// <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter" /> to write to.</param> 
     /// <param name="value">The value.</param> 
     /// <param name="serializer">The calling serializer.</param> 
     public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
     { 
      if (value is DateTime && (DateTime) value == DateTime.MinValue) 
      { 
       value = _zeroDateString; 
       serializer.Serialize(writer, value); 
      } 
      else 
      { 
       base.WriteJson(writer, value, serializer); 
      } 
     } 

     /// <summary> 
     /// Reads the JSON representation of the object. 
     /// If an input value is same a zeroDateString than DateTime.MinValue will be set as return value 
     /// </summary> 
     /// <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader" /> to read from.</param> 
     /// <param name="objectType">Type of the object.</param> 
     /// <param name="existingValue">The existing value of object being read.</param> 
     /// <param name="serializer">The calling serializer.</param> 
     /// <returns> 
     /// The object value. 
     /// </returns> 
     public override object ReadJson(JsonReader reader, Type objectType, object existingValue, 
      JsonSerializer serializer) 
     { 
      return reader.Value.ToString() == _zeroDateString 
       ? DateTime.MinValue 
       : base.ReadJson(reader, objectType, existingValue, serializer); 
     } 
    } 
} 
+3

爲什麼不簡單地在你的JSON中允許空值並且使用'DateTime?',而不是用哨兵值來彌補? .NET的「零日期」是0001-01-01,SQL Server不允許1753-01-01之前的日期,這個東西很快就會變得混亂。 – 2014-12-05 14:35:42

+0

將這些值存儲爲可以爲空的DateTime值可能是更好的方法。這可能容易實施。但我仍然需要處理傳入的「0000 ...」JSON值 – 2014-12-05 20:22:24

+0

使用示例註釋中的日期格式應該可能將小時指定爲24小時格式:「yyyy-MM-dd HH:mm:ss」 'yyyy-MM-dd hh:mm:ss'。 – bounav 2017-01-15 23:18:29

回答

1

你可以做到這一點使用ContractResolver如文檔中解釋說:

的IContractResolver接口提供了一種方式來定製JsonSerializer如何序列化和反序列化.NET對象,以JSON而不將屬性上你的類。 任何可以在對象,集合,屬性等上使用屬性或方法來控制序列化的設置也可以使用IContractResolver進行設置。

http://james.newtonking.com/json/help/index.html?topic=html/ContractResolver.htm

例子:

using System; 
using System.Windows.Forms; 
using Newtonsoft.Json; 
using Newtonsoft.Json.Converters; 
using Newtonsoft.Json.Serialization; 

namespace WindowsFormsApplication1 
{ 
    public partial class Form1 : Form 
    { 
     private string json = @" 
{ 
    ""Date"": ""0000-00-00 00:00:00"" 
} 
"; 

     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      var myClass = new MyClass(); 

      var deserializeObject = JsonConvert.DeserializeObject<MyClass>(json, 
       new JsonSerializerSettings {ContractResolver = new CustomDateContractResolver()}); 

      string serializeObject = JsonConvert.SerializeObject(myClass, Formatting.Indented, 
       new JsonSerializerSettings {ContractResolver = new CustomDateContractResolver()}); 
     } 
    } 

    internal class MyClass 
    { 
     public DateTime DateTime { get; set; } 
    } 

    internal class CustomDateContractResolver : DefaultContractResolver 
    { 
     protected override JsonContract CreateContract(Type objectType) 
     { 
      JsonContract contract = base.CreateContract(objectType); 
      bool b = objectType == typeof (DateTime); 
      if (b) 
      { 
       contract.Converter = new ZerosIsoDateTimeConverter("yyyy-MM-dd hh:mm:ss", "0000-00-00 00:00:00"); 
      } 
      return contract; 
     } 
    } 
} 

enter image description here

但作爲@Jeroen Mostert指出,你應該只使用 '常規' 行爲可能還沒有遇到之後會遇到麻煩,並且無論您使用日期,都必須遵循此自定義邏輯。