source

Json을 사용하여 dd/MM/yyy 형식으로 날짜를 역직렬화합니다.그물

factcode 2023. 3. 20. 23:37
반응형

Json을 사용하여 dd/MM/yyy 형식으로 날짜를 역직렬화합니다.그물

개체를 JSON 데이터에서 C# 클래스로 역직렬화하려고 합니다(Newtonsoft Json을 사용하고 있습니다).NET)에는 NET)와 같은 됩니다.09/12/2013은 " " " 입니다.dd/MM/yyyy.

가 ★★★★★★★★★★★★★★★★★★★★★★★★.JsonConvert.DeserializeObject<MyObject>(data)는 날날 , the DateTime을 C# 클래스의 MM/dd/yyyy은 "" "" " " " " " "가 됩니다.12 September 2013)9 December 2013를 참조해 주세요.

「」를 설정할 수 ?JsonConvert날짜를 올바른 형식으로 가져오려면 어떻게 해야 할까요?

'어울리지 않다'를 사용할 수 요.IsoDateTimeConverter해 주세요.DateTimeFormat을 사용법 §:

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

시작 섹션은 Newtown Soft 컨버터에 대한 내용이며, 리셋은 약입니다.Net Core Json Serializer, 이 답변을 처음 작성했을 때는 Microsoft 시리얼라이저가 없었기 때문에

주의: Newtown Soft와 Microsoft는 중복되는 이름이 매우 많으므로 올바른 네임스페이스를 사용하십시오.

Newtownsoft 시리얼라이저:

멀티 포맷 지원:

사용하는 것은 다음과 같습니다.

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

대안

다른 방법은 @pimbrowers가 말한 것과 같습니다.

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

}

커스텀 Date Time Converter

또, 커스텀 Date Time Converter에 해당하는 커스텀 Date Time Converter를 범위외의 형식이나 캘린더에 기입합니다.

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

주의:

다른 방법은 1회 구성되며, 보다 단순하고, 대부분의 경우 유용할 수 있습니다. 그러나 여기서 프로바이더는 각 개체에서 날짜를 2가지 형식으로 제공하는 서비스를 제공합니다. 그리고 이들 개체 중 하나는 각각 다른 달력으로 날짜를 2개씩 제공합니다.이 두 가지 방법을 알아두면 좋을 것 같습니다.

Microsoft 시리얼라이저:

[ASP.NET CORE MVC] 커스텀 Date Time Converter (기본 JSON 시리얼라이저 사용):

Microsoft 의 JSON 컨버터 실장은, Newtown Soft 의 실장과는 다릅니다.New Town Soft 플래그가 곧 내려지지 않기를 바랍니다.그들은 모든 것을 걸고 있지만, 사람들은 권력을 가진 사람들의 라이브러리를 이용하는 경향이 있습니다.그래서 여기 있습니다.

또한 Microsoft 구현에서는 Nullable과 Nullable이 아닌 각 유형의 데이터를 개별적으로 구현해야 합니다.

방법은 다음과 같습니다. 모든 공유 항목을 포함하는 기본 클래스를 만든 다음 각 버전에 대해 단순 파생된 항목을 만듭니다.

베이스:

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

다른 방법:

Microsoft 버전에서도 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");
        }
    }

}

양쪽 시리얼라이제이션 방식의 병행 사용:

2가지 환경에서의 컨버터(MVC Core 디폴트시리얼라이저 및 Newtown Soft)

Converter를 사용하려면 두 가지 환경에서 동일한 모델을 사용하는 경우 Newtown Soft와 Default serializer의 속성을 모두 적용하기만 하면 됩니다.이 두 가지 특성은 간섭되지 않고 정상적으로 작동합니다.인터페이스가 올바른지 확인만 하면 됩니다.

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

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

JsonSerializer에서도 설정할 수 있습니다.

var serializer = new JsonSerializer
{
    DateFormatString = "dd/MM/yyyy"
};

WebConfig에서 문화 추가:

<system.web>
   <globalization culture="pt-BR" uiCulture="pt-BR" enableClientBasedCulture="true"/>
</system.web>

그런 다음 아래 코드 스니펫을WebApiConfig.cs파일

var jsonFormatter =  GlobalConfiguration.Configuration.Formatters.JsonFormatter;
JsonSerializerSettings jSettings = new JsonSerializerSettings()
{
   Culture = System.Globalization.CultureInfo.CurrentCulture
};

jsonFormatter.SerializerSettings = jSettings;

문화pt-BR는 디폴트로 동작합니다.dd-MM-yyyy문화를 WebConfig에 넣지 않을 경우 해당 오브젝트에 대해서만 인스턴스를 만들 수 있습니다.

뉴턴소프트에 따르면 JsonSerializerSettings 클래스는

Date Format String(날짜 형식 문자열)

필드입니다.저도 제 프로젝트에서도 아래와 같은 방법으로 하고 있습니다.

string json = @"[
 '7 December, 2009',
 '1 January, 2010',
 10 February, 2010'
]";

IList<DateTime> dateList = JsonConvert.DeserializeObject<IList<DateTime>>(json, new 
JsonSerializerSettings
{
    DateFormatString = "d MMMM, yyyy"
});

foreach (DateTime dateTime in dateList)
{
   Console.WriteLine(dateTime.ToLongDateString());
}
// Monday, 07 December 2009
// Friday, 01 January 2010
// Wednesday, 10 February 2010

제 경험상 가장 간단하고 쉬운 해결책은 항상 다음 사항을 추가하는 것입니다.stringCLR 오브젝트의 속성(MyObject)를 참조해 주세요.사용하는 넷.또, 오브젝트에는DateTime속성(getter 전용)은 JSON을 사용하여 역직렬화한 datetime 문자열을 해석합니다.원하는 형식으로 넷을 만듭니다.

이를 통해 개봉 즉시 디시리얼라이저를 사용할 수 있으며, 작업을 완료하기 위해 좋은 ol'formed c#에 의존할 수 있습니다.긁어부스럼.

public class MyObject
{
    public string dtStr { get; set; }
    public DateTime? dt
    {
        get
        {
            DateTime? d = null;

            if (!string.IsNullOrWhiteSpace(dtStr) && DateTime.TryParseExact(dtStr, "dd/mm/yyyy", CultureInfo.InvariantCultureDateTimeStyles.None, out d)
            {
                return d;
            }

            return d;
        }
    }
}

사실 위에서 언급한 것 중 어느 것도 제 문제를 완전히 해결하지 못했습니다.나는 그것을 알았다if any of my column data is null then NewtonSoft.JSON will suffer.데이터셋을 서비스에서 시리얼화하고 UI에서 디시리얼라이즈한 경우입니다.설정일절 제공되지 않았습니다.기본적으로 아래 두 가지 설정을 모두 서비스(JsonConvert)에서 추가한 것입니다.SerializeObject) 및 UI(JsonConvert)에 있습니다.디시리얼라이즈 오브젝트)

 var settings = new JsonSerializerSettings
 {
       Culture = new System.Globalization.CultureInfo("tr-TR"),
       DateFormatString = "dd.MM.yyyy",
       NullValueHandling = NullValueHandling.Ignore
 };

편집: 위의 작업을 수행했을 때,Newtonsoft역직렬화 중에 열 순서가 변경됩니다.이러한 설정 대신 변경만 하면 됩니다.serialize설정service아래 코드로 레이어하면 모든 것이 기대했던 대로 작동하기 시작합니다.

string serializedDataSet= JsonConvert.SerializeObject(dataset, Formatting.Indented, new IsoDateTimeConverter { DateTimeFormat = "dd.MM.yyyy" });

@pim에 의한 답변을 바탕으로 한 솔루션을 소개합니다.

void Main()
{
  var value = "{\"availableFrom\":\"2022-01-01\",\"availableTo\":\"null\"}";
  var dates = Newtonsoft.Json.JsonConvert.DeserializeObject<ItemOptionAvailablePeriod>(value);
  value.Dump();
  dates.Dump();
}

public class ItemOptionAvailablePeriod
{
  private string _format = "yyyy-MM-dd";
  
  public string AvailableFrom { get; set; }
  public string AvailableTo{ get; set; }
  public DateTime? AvailableFromDate
  {
    get
    {
      if(!string.IsNullOrEmpty(AvailableFrom) && DateTime.TryParseExact(AvailableFrom, _format, CultureInfo.InvariantCulture, DateTimeStyles.None, out var d)) {
        return d;
      }
      return null;
    }
  }
  public DateTime? AvailableToDate
  {
    get
    {
      if (!string.IsNullOrEmpty(AvailableTo) && DateTime.TryParseExact(AvailableTo, _format, CultureInfo.InvariantCulture, DateTimeStyles.None, out var d))
      {
        return d;
      }
      return null;
    }
  }
}

.Dump() 부분:

여기에 이미지 설명 입력

언급URL : https://stackoverflow.com/questions/21256132/deserializing-dates-with-dd-mm-yyyy-format-using-json-net

반응형