json.net: DateTimeStringConverter получает уже преобразованный объект DateTime в ReadJson ()

2

Предпосылки:

  • JSON.Net 11.0.2

Мне нужно сохранить шаблон даты/времени UTC DateTime в оба конца через REST-API на основе JSON.

string utcTimestamp = DateTime.UtcNow.ToString( "o" );
// 2018-11-27T22:35:32.1234567Z

Поэтому я написал себе DateTimeStringConverter чтобы гарантировать, что информация о местной культуре не участвует

class DateTimeStringConverter:
    JsonConverter<DateTime>
{
    public override void WriteJson( JsonWriter writer, DateTime value, JsonSerializer serializer )
    {
        string convertedValue = value.ToString( "o" );
        writer.WriteValue( convertedValue );
    }

    public override DateTime ReadJson( JsonReader reader, Type objectType, DateTime existingValue, bool hasExistingValue, JsonSerializer serializer )
    {
        string value = reader.Value.ToString( );
        DateTime convertedValue = DateTime.Parse( value ).ToLocalTime( );
        return convertedValue;
    }
}

Я был очень смущен тем, почему я получаю объект DateTime без миллисекунд. После долгих проб и ошибок я попал в это.

public override DateTime ReadJson( JsonReader reader, Type objectType, DateTime existingValue, bool hasExistingValue, JsonSerializer serializer )
{
    Console.WriteLine( reader.Value.GetType( ).ToString( ) );
    // System.DateTime

    string value = reader.Value.ToString( );
    DateTime convertedValue = DateTime.Parse( value ).ToLocalTime( );
    return convertedValue;
}

JSON.Net предоставляет мне уже преобразованный объект DateTime для самостоятельной десериализации без каких-либо миллисекундных данных. Я не нашел никаких подсказок относительно того, является ли это ошибкой или функцией.

Чтобы проверить это, я написал BooleanStringConverter.

class BoolStringConverter:
    JsonConverter<bool>
{
    public override void WriteJson( JsonWriter writer, bool value, JsonSerializer serializer )
    {
        string convertedValue = false == value ? "False" : "True";
        writer.WriteValue( convertedValue );
    }

    public override bool ReadJson( JsonReader reader, Type objectType, bool existingValue, bool hasExistingValue, JsonSerializer serializer )
    {
        Console.WriteLine( reader.Value.GetType( ).ToString( ) );
        // System.String

        string value = ( string ) reader.Value;
        bool convertedValue = "False" == value ? false : true;
        return convertedValue;
    }
}

JSON.Net не обслуживает меня уже преобразованный объект bool.

Это баг или фича?

  • 2
    Если вы используете свой собственный конвертер для дат, обязательно установите для параметра DateParseHandling значение None в JsonSerializerSettings , в противном случае внутреннее устройство чтения сначала попытается обработать его.
  • 0
    @BrianRogers Вы получили это. Напишите это и я отмечу это.
Теги:
deserialization
datetime
json.net

1 ответ

1
Лучший ответ

Это известное поведение Json.Net. Поскольку JSON не имеет встроенного синтаксиса для обозначения дат (как это имеет место для логических значений), они должны быть представлены в виде строк. По умолчанию Json.Net пытается быть красивым и анализирует строки, похожие на даты.

Если вы используете свой собственный конвертер для дат или иным образом хотите обрабатывать данные самостоятельно, вам нужно обязательно установить для параметра DateParseHandling значение None в JsonSerializerSettings, иначе внутренний читатель попытается обработать его первым.

JsonSerializerSettings settings = new JsonSerializerSettings
{
    Converters = new List<JsonConverter> { new DateTimeStringConverter() },
    DateParseHandling = DateParseHandling.None
};

var foo = JsonConvert.DeserializeObject<Foo>(json, settings);
  • 0
    Я только что видел это прямо сейчас. Зачем вы поместили конвертеры в список? Эти настройки работают только на этих конвертерах? Если бы у меня было другое строковое значение DateTime с преобразователем, которого нет в списке, будет ли это значение предварительно проанализировано?
  • 0
    Нет, параметр DateParseHandling будет по-прежнему применяться ко всем конвертерам независимо от того, помещаете ли вы конвертеры в список в настройках или используете ли вы атрибуты [JsonConverter] в ваших классах. Я просто собрал их здесь, чтобы показать типичный пример использования.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню