当前位置: 首页 > 知识库问答 >
问题:

使用Json以dd/MM/yyyy格式反序列化日期。网

杜俊爽
2023-03-14

我正在尝试将一个对象从JSON数据反序列化为C类(我使用的是Newtonsoft JSON.NET)。数据以字符串值形式包含日期,如2013年12月9日,格式为年月日。

如果我调用JsonConvert。反序列化对象

是否可以配置JsonConvert以获得正确格式的日期?

共有3个答案

司徒宇
2023-03-14
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

var dateTimeConverter = new IsoDateTimeConverter { DateTimeFormat = "dd/MM/yyyy" };
myObject obj = JsonConvert.DeserializeObject<myObject>(myJSONString, dateTimeConverter);
国胤
2023-03-14

开始部分是关于Newtown Soft转换器的,重置是关于. Net Core Json序列化器的,因为我第一次写这个答案时没有Microsoft序列化器

注意:Newtown Soft和Microsoft有很多重叠的名称,请确保使用正确的名称空间

这就是我所使用的:

public class CustomDateTimeConverter : IsoDateTimeConverter
{
    public CustomDateTimeConverter()
    {
        base.DateTimeFormat = "dd/MM/yyyy";
    }
}

然后你会这样做:

public class MyObject
{
    [JsonConverter(typeof(CustomDateTimeConverter))]
    public DateTime Date {get;set;}
}

然后用你以前做过的任何正常方式反序列化...

MyObject obj = JsonConvert.DeserializeObject<MyObject>(json);

其他方式与@pimbrouwers所说的相同:

public class MyObject
{
    [JsonProperty("Date")] //Naturally Case Sensetive
    private string dateJson {get;set;}
    // it would be good to look at @pimbrouwers answer and use nullable
    [JsonIgnore]
    public DateTime Date
    {
        get
        {
            return DateTime.ParseExact(dateJson,"dd/MM/yyyy",CultureInfo.InvariantCulture);
        }
        set
        {
            dateJson = value.ToString("dd/MM/yyyy");
        }
    }

}

我还写了一个自定义日期时间转换器,它可以匹配自定义的范围外格式或日历

public class CustomDateTimeConverterJalali : DateTimeConverterBase
{
    //I had no use for WriteJson section, i just wrote it, so i do not guarantee it working
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        if (value == null)
        {
            writer.WriteNull();
            return;
        }

        var nullableType = Nullable.GetUnderlyingType(value.GetType());
        var isNullable = nullableType != null;

        DateTime date;
        if (isNullable)
            date = ((DateTime?) value).Value;
        else
            date = (DateTime) value;


        PersianCalendar pc = new PersianCalendar();

        writer.WriteValue(pc.GetYear(date) + "/" + pc.GetMonth(date) + "/" + pc.GetDayOfMonth(date));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        //this should likely be null, but since the provider json returned empty string, it was unavoidable... (i'm not sure what we will read using reader, if data is actually null on the json side, feel free to experiment 
        if (string.IsNullOrWhiteSpace((string) reader.Value))
        {
            return null;
        }

        var strDate = reader.Value.ToString();

        PersianCalendar pc = new PersianCalendar();
        var dateParts = strDate.Split('/');

        DateTime date = pc.ToDateTime(int.Parse(dateParts[0]), int.Parse(dateParts[1]), int.Parse(dateParts[2]),
            0, 0, 0, 0);

        return date;
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(DateTime);//DateTime=>true | DateTime?=>true
    }
}

您提供的其他方法是一次性配置的,可能更简单,并且在大多数情况下都很有用,。。。但在这里,提供者为我提供了一个服务,它在每个对象中以两种格式提供日期,其中一个对象在不同的日历中提供两个日期。。。很高兴知道我在这里提供的两种方法

请注意,JSON转换器的Microsoft实现与NewtownSoft实现不同。我希望NewtownSoft的旗帜不会很快降下来,因为他们将毕生精力都放在了这面旗帜上,但人们倾向于使用权力阶层的图书馆,所以它就在这里。

还要注意,Microsoft实现要求您实现每种类型的数据,分别包括可为null的和不可为null的。

我是这样做的,我创建了一个包含所有共享内容的基类,然后为每个版本创建一个简单的派生类。

基础:

using System;
using System.Buffers;
using System.Buffers.Text;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Charter724.Helper.JsonConverter.Microsoft
{
    /// <summary>
    /// Base Custom Format DateTime Handler <br/>
    /// using System.Text.Json.Serialization;
    /// </summary>
    [SuppressMessage("ReSharper", "RedundantBaseQualifier")]
    public class MsBaseDateTimeConverter<T> : JsonConverter<T>
    {
        private const string DefaultDateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK";

        private readonly string _format;
        private readonly CultureInfo _culture;
        private readonly DateTimeStyles _dateTimeStyles;

        public MsBaseDateTimeConverter(string format, CultureInfo culture = null, DateTimeStyles dateTimeStyles= DateTimeStyles.RoundtripKind)
        {
            _format = format;

            if (culture == null)
            {
                _culture = CultureInfo.CurrentCulture;
            }

            _dateTimeStyles = dateTimeStyles;

        }

        public override bool CanConvert(Type typeToConvert)
        {
            if (typeToConvert == typeof(DateTime) || typeToConvert == typeof(DateTime?))
            {
                return true;
            }

            return false;
        }

        public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            bool nullable = ReflectionUtils.IsNullableType(typeToConvert);
            if (reader.TokenType == JsonTokenType.Null)
            {
                if (!nullable)
                {
                    throw new JsonException();
                }

                return default;
            }

            if (_format != null)
            {
                if (DateTime.TryParseExact(reader.GetString(), _format, _culture, _dateTimeStyles,
                    out var dtValue))
                {
                    return (T) (object) dtValue;
                }

                throw new JsonException();
            }
            else
            {
                // try to parse number directly from bytes
                ReadOnlySpan<byte> span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan;
                if (Utf8Parser.TryParse(span, out DateTime dtValue, out int bytesConsumed) &&
                    span.Length == bytesConsumed)
                    return (T) (object) dtValue;

                // try to parse from a string if the above failed, this covers cases with other escaped/UTF characters
                if (DateTime.TryParse(reader.GetString(), out dtValue))
                    return (T) (object) dtValue;

                return (T) (object) reader.GetDateTime();
            }
        }

        public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
        {
            if (value != null)
            {
                if (value is DateTime dateTime)
                {
                    if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal
                        || (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal)
                    {
                        dateTime = dateTime.ToUniversalTime();
                    }

                    var text = dateTime.ToString(_format ?? DefaultDateTimeFormat, _culture);
                    writer.WriteStringValue(text);
                }
                else
                {
                    throw new JsonException();
                }
                return;
            }

            writer.WriteNullValue();

        }
    }
}

不可为null的派生值:

using System;
using System.Diagnostics.CodeAnalysis;

namespace Charter724.Helper.JsonConverter.Microsoft
{
    /// <summary>
    /// Format: yyyy-MM-dd - NOT NULL <br/>
    /// Microsoft <br/>
    /// using System.Text.Json.Serialization;
    /// </summary>
    [SuppressMessage("ReSharper", "RedundantBaseQualifier")]
    public class MsCustomDateTimeConverter : MsBaseDateTimeConverter<DateTime>
    {
        public MsCustomDateTimeConverter():base("yyyy-MM-dd")
        {
            //base.DateTimeFormat = "yyyy-MM-dd";
        }
    }
}

nullable的派生值:

using System;
using System.Diagnostics.CodeAnalysis;

namespace Charter724.Helper.JsonConverter.Microsoft
{
    /// <summary>
    /// Format: yyyy-MM-dd - NULLABLE <br/>
    /// Microsoft <br/>
    /// using System.Text.Json.Serialization;
    /// </summary>
    [SuppressMessage("ReSharper", "RedundantBaseQualifier")]
    public class MsCustomDateTimeConverterNullable : MsBaseDateTimeConverter<DateTime?>
    {
        public MsCustomDateTimeConverterNullable():base("yyyy-MM-dd")
        {
            //base.DateTimeFormat = "yyyy-MM-dd";
        }
    }
}

使用详情:

public class MyObject
{
    [System.Text.Json.Serialization.JsonConverter(typeof(MsCustomDateTimeConverter))]
    public DateTime Date { set; get; }
}

我没有测试微软版本是否也支持JsonProperty的私有成员,但由于EF Core在这件事上失败了,我只是想注意一下这件事,以防它不起作用。

public class MyObject
{
    [JsonProperty("Date")] //Naturally Case Sensetive
    private string dateJson {get;set;}
    // it would be good to look at @pimbrouwers answer and use nullable
    [JsonIgnore]
    public DateTime Date
    {
        get
        {
            return DateTime.ParseExact(dateJson,"dd/MM/yyyy",CultureInfo.InvariantCulture);
        }
        set
        {
            dateJson = value.ToString("dd/MM/yyyy");
        }
    }

}

要在使用相同模型的两个环境中使用转换器,您所要做的就是应用NewtownSoft和默认序列化程序的两个属性,这两个属性不会相互干扰,并且工作正常。只要确保你的界面是正确的。

public class MyObject
{
    [System.Text.Json.Serialization.JsonConverter(typeof(MsCustomDateTimeConverter))]
    [Newtonsoft.Json.JsonConverter(typeof(NsCustomDateTimeConverter))]
    public DateTime Date { set; get; }
}
支洋
2023-03-14

您可以使用IsoDateTimeConverter并指定日期时间格式以获得所需的结果,例如:

MyObject obj = JsonConvert.DeserializeObject<MyObject>(jsonString, 
                   new IsoDateTimeConverter { DateTimeFormat = "dd/MM/yyyy" });

演示:

class Program
{
    static void Main(string[] args)
    {
        string json = @"{ ""Date"" : ""09/12/2013"" }";

        MyObject obj = JsonConvert.DeserializeObject<MyObject>(json, 
            new IsoDateTimeConverter { DateTimeFormat = "dd/MM/yyyy" });

        DateTime date = obj.Date;
        Console.WriteLine("day = " + date.Day);
        Console.WriteLine("month = " + date.Month);
        Console.WriteLine("year = " + date.Year);
    }
}

class MyObject
{
    public DateTime Date { get; set; }
}

输出:

day = 9
month = 12
year = 2013
 类似资料:
  • 问题内容: 我正在尝试从转换日期。我已经使用了mktime()函数和其他函数,但是我似乎无法使其工作。我已经成功地将原始日期用作定界符,但更改格式并将其与交换时没有成功。 任何帮助将不胜感激。 问题答案: 通过查看各个组成部分之间的分隔符,可以消除或格式中的日期的歧义:如果该分隔符是斜杠(),则假定为American ;否则,为0。反之,如果分隔符是破折号()或点(),则采用欧洲格式。 使用默认的

  • 我有一个格式为。我希望它的格式为 下面是我尝试进行此转换的示例util: 但是,我得到的输出不是格式。 请告诉我如何将从格式化为

  • 我从格式为yyyy-mm-dd(加上不需要的hh-mm-ss)的API中获取日期结果。我想在jQuery中将其转换为dd-mm-yyyy格式,最简单/最快的方法是什么? 目前我正在使用:(对于返回的字符串yyyy-mm-dd): 但是好像有点啰嗦。

  • 问题内容: 好吧,我正在使用a进行详细说明,因为我从数据库中获取了一个对象,并且从同一对象中获得了一个变量“ fecha”(日期),因此我得到了a ,因此formatt以毫秒为单位,但是我不想出现毫秒。因此,我需要将我从数据库中收到的日期格式化为没有毫秒的新日期。 这是对象Factura: 在映射到数据库的xml中,我具有该变量“ fecha”的代码: 在数据库中,该列为。 当我从数据库中获取一个

  • 问题内容: 如何检查SQL Server中日期字符串是否为MM / DD / YYYY格式? 问题答案: 如果结果为1,则为有效日期,但不能保证其为用户指定的日期。如果他们输入: 没有办法知道是6月7日还是7月6日。最好的办法是让用户从下拉列表或日历控件中选择日期,这使您可以控制格式并避免不必要的解释。您的应用程序层可以使用强类型变量/参数,然后插入正确类型的列中。

  • 问题内容: 我想在Java中解析这种格式为dd / MM / yyyy [至dd / MM / yyyy]的String的最佳方法是什么。带[]的字符串是可选的,dd代表日期的2位数字表示,MM是月份的2位数字表示,yyyy是年份的4位数字表示。 更新资料 谢谢大家的快速响应,但是我忘了告诉您[]是象征可选的,字符串中没有[]示例字符串可能是 22/01/2010 从22/01/2010至23/0