使用零值转换JSON DateTime值的最佳方法(例如" 0000-00-00 00:00:00")

时间:2014-12-05 13:42:47

标签: c# datetime json.net converter

仅使用零(例如“0000-00-00 00:00:00”)转换JSON DateTime值不适用于标准Json.net IsoDateTimeConverter。我开发了一个自定义转换器,保存了这个值DateTime.MinValue。 DateTime.MinValue也将被写为“ZeroDateString”。所有其他字符串由基本IsoDateTimeConverter类处理。 我在JsonNet注释上使用这个转换器来获取DateTime属性。

是否有更好,更简单的方法来解决这个问题,例如:在基本水平,没有需要注释?

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);
        }
    }
}

2 个答案:

答案 0 :(得分:2)

您可以使用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 指出的那样,您应该使用“常规”行为,以便以后可能不会遇到麻烦,并且无论您何时使用日期,都必须遵循此自定义逻辑。

答案 1 :(得分:1)

我遇到了同样的问题,我为此使用了自定义转换器......

class MyDateConverter: Newtonsoft.Json.Converters.IsoDateTimeConverter
{
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.Value != null && reader.Value.ToString().StartsWith("0000")) return null;
        else return base.ReadJson(reader, objectType, existingValue, serializer);
    }
}