gpt4 book ai didi

c# - 测试自定义 JsonConverter 时出现异常

转载 作者:行者123 更新时间:2023-12-04 00:02:11 27 4
gpt4 key购买 nike

我们以一种奇怪的格式从 API 获取序列化的 DateTimes:/Date(1574487012797)/为了使用 System.Text.Json 反序列化这个值,我们编写了自己的 JsonConverter:

public class DateTimeConverter : JsonConverter<DateTime>
{
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var dateTimeString = reader.GetString();
dateTimeString = dateTimeString.Replace("/Date(", "");
dateTimeString = dateTimeString.Replace(")/", "");
var epoch = Convert.ToInt64(dateTimeString);
var dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(epoch);
return dateTimeOffset.UtcDateTime;
}

public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"));
}
}

我想为此转换器编写单元测试。我尝试的是以下内容:

public class DateTimeConverterTest
{
private readonly DateTimeConverter testee;

public DateTimeConverterTest()
{
this.testee = new DateTimeConverter();
}

[Fact]
public void Read_WhenCalledWithSerializedDateTime_ThenReturnDeserializedDateTime()
{
var a = "{\r\n \"PublikationsDatum\": \"/Date(1573581177000)/\" \r\n}";
//var serializedDateTime = "/Date(1573581177000)/";
var utf8JsonReader = new Utf8JsonReader(Encoding.UTF8.GetBytes(a), false, new JsonReaderState(new JsonReaderOptions()));
//utf8JsonReader.TokenType = JsonTokenType.String;
var deserializedDateTime = this.testee.Read(ref utf8JsonReader, typeof(DateTime), new JsonSerializerOptions {IgnoreNullValues = true});

}

private class TestClass
{
public DateTime PublikationsDatum { get; set; }
}
}

不幸的是,在尝试执行单元测试时,我在 var dateTimeString = reader.GetString();

处收到 InvalidOperationException

System.InvalidOperationException: 'Cannot get the value of a token type 'None' as a string.'

如何正确设置测试/我做错了什么?

最佳答案

在调用 JsonConverter<T>.Read() 之前,您必须将 Utf8JsonReader 向前移动,直到它位于"PublikationsDatum"属性的值上,例如像这样:

public void Read_WhenCalledWithSerializedDateTime_ThenReturnDeserializedDateTime()
{
var a = "{\r\n \"PublikationsDatum\": \"/Date(1573581177000)/\" \r\n}";
var utf8JsonReader = new Utf8JsonReader(Encoding.UTF8.GetBytes(a), false, new JsonReaderState(new JsonReaderOptions()));
while (utf8JsonReader.Read())
if (utf8JsonReader.TokenType == JsonTokenType.String)
break;
var deserializedDateTime = this.testee.Read(ref utf8JsonReader, typeof(DateTime), new JsonSerializerOptions {IgnoreNullValues = true});
}

演示 fiddle #1 here

或者,您可以通过解析简单的 JSON 字符串文字"/Date(1573581177000)/"来简化单元测试。但是,您仍然需要将阅读器推进一次,因为它最初位于第一个标记的开头之前,即utf8JsonReader.TokenType == JsonTokenType.None:

public void Read_WhenCalledWithSerializedDateTime_ThenReturnDeserializedDateTime()
{
var a = "\"/Date(1573581177000)/\"";
var utf8JsonReader = new Utf8JsonReader(Encoding.UTF8.GetBytes(a), false, new JsonReaderState(new JsonReaderOptions()));
// Reader always starts out without having read anything yet, so TokenType == JsonTokenType.None initially
Assert.IsTrue(utf8JsonReader.TokenType == JsonTokenType.None);
utf8JsonReader.Read();
var deserializedDateTime = this.testee.Read(ref utf8JsonReader, typeof(DateTime), new JsonSerializerOptions {IgnoreNullValues = true});
}

演示 fiddle #2 here

注意事项:

  • "\/Date(number of ticks)\/"是微软最初的JavaScriptSerializer用于将DateTime序列化为JSON字符串的格式。详情请参阅the documentation remarks

(在 JSON string literal 中,\/ 只是一个转义的 \ 并将被 Utf8JsonReader 默默地解释为这样,参见 fiddle #3 here 。你不需要检查\/在您的 JSON 转换器中处理JavaScriptSerializer生成的日期和时间。)

  • DataContractSerializer使用了稍微不同的格式。来自docs:

    DateTime values appear as JSON strings in the form of "/Date(700000+0500)/", where the first number (700000 in the example provided) is the number of milliseconds in the GMT time zone, regular (non-daylight savings) time since midnight, January 1, 1970. The number may be negative to represent earlier times. The part that consists of "+0500" in the example is optional and indicates that the time is of the Local kind - that is, should be converted to the local time zone on deserialization. If it is absent, the time is deserialized as Utc. The actual number ("0500" in this example) and its sign (+ or -) are ignored.

  • Newtonsoft 对 DateTimeUtils.TryParseDateTimeMicrosoft() 的实现可能有助于指导您的实现。

关于c# - 测试自定义 JsonConverter 时出现异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59028159/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com