System.Text. Json Пользовательский метод JsonConverter <DateTime>.Read () не используется .Deserialize () - PullRequest
3 голосов
/ 14 января 2020

У меня проблемы с System.Text. Json и пользовательскими форматами даты и времени.

Я создал собственный конвертер, и он работал в моем проекте API. Когда я собирал свой клиент, я пытался использовать тот же класс, но методы .Deserialize () не будут вызывать .Read () для свойства DateTime моего класса.

Кто-нибудь сталкивался с такой же проблемой?

public class DateTimeConverter : JsonConverter<DateTime>
{
    private static readonly string _format = "yyyy-MM-dd'T'HH:mm:ss.fff";

    public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return DateTime.ParseExact(reader.GetString(), _format, System.Globalization.CultureInfo.InvariantCulture);
    }

    public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
    => writer.WriteStringValue(value.ToUniversalTime().ToString(_format));
}

public async Task<StockUnitInfo> GetStockUnitInfoAsync(Inbound inbound, CancellationToken token = default)
{
    var uri = Uri.EscapeUriString($"{_httpClient.BaseAddress}/Readers/{inbound.Position}/StockUnits/{inbound.Barcode}");

    var test = await _httpClient.GetStringAsync(uri);

    var response = await _httpClient.GetStreamAsync(uri);

    var _serializationOptions = new JsonSerializerOptions
    {
        Converters = { new DateTimeConverter() }
    };

    return await JsonSerializer.DeserializeAsync<StockUnitInfo>(response, _serializationOptions, token);
}

public class StockUnitInfo
{
    public string barcode { get; set; }
    public string wms_batch_id { get; set; }
    public string gtin { get; set; }

    //[JsonConverter(typeof(DateTimeConverter))]
    public DateTime sort_date { get; set; }
    public string talleys_batch_number { get; set; }
    public int expected_batch_size { get; set; }
    public string destination { get; set; }
    public bool fast_mover { get; set; }
    public int stackable { get; set; }
    public string message { get; set; }
}

Минимальный воспроизводимый пример по запросу:

using System;
using System.Text.Json;
using System.Text.Json.Serialization;

class Program
{
    public class DateTimeConverter : JsonConverter<DateTime>
    {
        //private static readonly string _format = "yyyy.MM.dd'T'HH:mm:ss.fff'Z'";  //formato api?
        private static readonly string _format = "yyyy-MM-dd'T'HH:mm:ss.fff";


        public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            return DateTime.ParseExact(reader.GetString(), _format, System.Globalization.CultureInfo.InvariantCulture);
        }

        public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
        => writer.WriteStringValue(value.ToUniversalTime().ToString(_format));
    }
    public class StockUnitInfo
    {
        public string barcode { get; set; }
        public string wms_batch_id { get; set; }
        public string gtin { get; set; }

        //[JsonConverter(typeof(DateTimeConverter))]
        public DateTime sort_date { get; set; }
        public string talleys_batch_number { get; set; }
        public int expected_batch_size { get; set; }
        public string destination { get; set; }
        public bool fast_mover { get; set; }
        public int stackable { get; set; }
        public string message { get; set; }
    }
    public static void Main(string[] args)
    {
        string json = "{\"barcode\":\"201930823\",\"wmsBatchId\":\"c3e4d921-8779-46f7-ac28-b1f523845329\",\"gtin\":\"01080\",\"sortDate\":\"2019-09-20T11:59:59.999\",\"talleysBatchNumber\":\"STK0233\",\"expectedBatchSize\":1,\"destination\":\"5A05\",\"fastMover\":false,\"stackable\":0,\"message\":\"Pallet directed to CS4\"}";

        var _serializationOptions = new JsonSerializerOptions
        {
            Converters = { new DateTimeConverter() }
        };
        var result = JsonSerializer.Deserialize<StockUnitInfo>(json, _serializationOptions);

        Console.WriteLine(result.sort_date);
        Console.Read();
    }
}

1 Ответ

3 голосов
/ 14 января 2020

Причина в том, что имя свойства класса и имя свойства Json различаются:

"sortDate": "2019-09-20T11:59:59.999"

И

public DateTime sort_date { get; set; }

Для десериализации этого json необходимо либо сделать имена одинаковыми, либо указать сериализатору, что делать, добавив атрибут чтобы сказать, каково эквивалентное имя:

[JsonPropertyName("sortDate")]
public DateTime sort_date { get; set; }

Как только это будет добавлено, ваш пример кода будет работать правильно:

enter image description here

...