Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 测试自定义JsonConverter时出现异常_C#_.net_Json_.net Core 3.0_System.text.json - Fatal编程技术网

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

C# 测试自定义JsonConverter时出现异常,c#,.net,json,.net-core-3.0,system.text.json,C#,.net,Json,.net Core 3.0,System.text.json,我们从一个API中以如下奇怪的格式获得序列化的日期时间:/Date(157448712797)/ 为了用System.Text.Json反序列化该值,我们编写了自己的JsonConverter: public class DateTimeConverter : JsonConverter<DateTime> { public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSe

我们从一个API中以如下奇怪的格式获得序列化的日期时间:
/Date(157448712797)/
为了用
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"));
    }
}
不幸的是,在尝试执行单元测试时,我在
var dateTimeString=reader.GetString()处得到了一个
invalidoOperationException

System.InvalidOperationException:'无法将令牌类型'None'的值作为字符串获取。'

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

在调用之前,您必须提前,直到它位于
“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});
}
演示小提琴#1

或者,您可以通过解析一个简单的JSON字符串literal
“/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});
}
演示小提琴2

注:

  • “\/Date(刻度数)\/”
    是Microsoft原始的
    JavaScriptSerializer
    用于将
    日期时间
    序列化为JSON字符串的格式。有关详细信息,请参阅

    (在JSON中,
    \/
    只是一个转义的
    \
    ,将由
    Utf8JsonReader
    以静默方式解释,请参见FIDLE 3。您不需要在JSON转换器中检查
    \/
    来处理
    JavaScriptSerializer
    生成的日期和时间。)

  • DataContractSerializer
    使用了稍微不同的格式。从:

    DateTime值以“/Date(700000+0500)/”的形式显示为JSON字符串,其中第一个数字(提供的示例中为700000)是GMT时区的毫秒数,即自1970年1月1日午夜起的常规(非夏令时)时间。该数字可能为负数,以表示较早的时间。示例中由“+0500”组成的部分是可选的,指示时间是本地类型的-也就是说,应在反序列化时转换为本地时区。如果不存在,则将时间反序列化为Utc。忽略实际数字(本例中为“0500”)及其符号(+或-)

  • Newtonsoft的实现可能有助于指导您的实现

真棒的答案!我有一个和OP完全相同的问题(和类似的代码),所以这是非常好的时机和帮助。做得好!
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});
}