在命名空间中找不到 System.Text.Json.JsonReaderException

Nam*_*kwl 11 c# json nunit .net-core system.text.json

我正在将 .NET Framework 4.5 项目转换为 .NET Core 3.1。我的测试过去使用 Newtonsoft.Json 来检查 json 是否有效,现在我想使用内置的 System.Text.Json 来实现相同的功能。看起来

JsonElement values = JsonDocument.Parse(json).RootElement;
Run Code Online (Sandbox Code Playgroud)

throws System.Text.Json.JsonReaderException,但我无法捕获它,因为指向此异常会导致错误

命名空间“System.Text.Json”中不存在类型或命名空间名称“JsonReaderException”(您是否缺少程序集引用?)

我只是想了解如何可能抛出实际上似乎不存在的东西。

更新#1:堆栈跟踪:

   at System.Text.Json.ThrowHelper.ThrowJsonReaderException(Utf8JsonReader& json, ExceptionResource resource, Byte nextByte, ReadOnlySpan`1 bytes)
   at System.Text.Json.Utf8JsonReader.ReadSingleSegment()
   at System.Text.Json.Utf8JsonReader.Read()
   at System.Text.Json.JsonDocument.Parse(ReadOnlySpan`1 utf8JsonSpan, Utf8JsonReader reader, MetadataDb& database, StackRowStack& stack)
   at System.Text.Json.JsonDocument.Parse(ReadOnlyMemory`1 utf8Json, JsonReaderOptions readerOptions, Byte[] extraRentedBytes)
   at System.Text.Json.JsonDocument.Parse(ReadOnlyMemory`1 json, JsonDocumentOptions options)
   at System.Text.Json.JsonDocument.Parse(String json, JsonDocumentOptions options)
   at Anonymized..ctor(String json) in Anonymized.cs:line 182
   at Anonymized.<>c__DisplayClass12_0.<TestCreateLogEntryFromJson_IllegalValues>b__0() in Anonymized.cs:line 206
   at NUnit.Framework.Assert.Throws(IResolveConstraint expression, TestDelegate code, String message, Object[] args)
Run Code Online (Sandbox Code Playgroud)

更新#2:我去看看是否有一些我遗漏的东西。我发现 System.Text.Json 作为 nuget(尽管它已经可以访问,但我在测试文件中成功使用了 System.Text.JsonSerializer)。我添加了它,现在我遇到了实际问题:由于其保护级别,它无法访问。

using System.Text.Json;

namespace System.Text.Json
{
    internal sealed class JsonReaderException : JsonException
    {
        public JsonReaderException(string message, long lineNumber, long bytePositionInLine);
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,这并不能直接解决问题,我如何才能抓住这个问题Assert.Throws<System.Text.Json.JsonReaderException>

dbc*_*dbc 9

System.Text.Json.JsonReaderException目前的事实internal表明,微软可能随时修改或删除该类型,并且用户不System.Text.Json应该依赖该类作为 public 的子类继续存在JsonException。事实上,文档Utf8JsonReader仅说明

Utf8JsonReader遇到无效的 JSON 时,它会抛出一个JsonException带有基本错误信息的错误信息,例如行号和行上的字节位置。

以及状态的代码注释JsonReaderException

// This class exists because the serializer needs to catch reader-originated exceptions in order to throw JsonException which has Path information.
Run Code Online (Sandbox Code Playgroud)

相反,断言抛出的异常是JsonException通过使用Is.InstanceOf<JsonException>()

Assert.Throws(Is.InstanceOf<JsonException>(), () => JsonDocument.Parse(json).Dispose());
Run Code Online (Sandbox Code Playgroud)

如果由于某种原因您必须断言抛出的特定异常类型,您可以利用Assert.Throws()返回抛出的异常的事实来检查异常的完整类型名称:

Assert.AreEqual("System.Text.Json.JsonReaderException",
                Assert.Throws(Is.InstanceOf<JsonException>(), () => JsonDocument.Parse(json).Dispose()).GetType().FullName);
Run Code Online (Sandbox Code Playgroud)

或者您可以使用 NUnit 的自定义约束机制并引入FullTypeNameConstraint如下所示:

using NUnit.Framework;
using NUnit.Framework.Constraints;

public class FullTypeNameConstraint : Constraint
{
    readonly string expectedFullTypeName;

    public FullTypeNameConstraint(string expectedFullTypeName) : base(expectedFullTypeName) => this.expectedFullTypeName = expectedFullTypeName;

    public override string DisplayName => "FullTypeNameOf";

    public override ConstraintResult ApplyTo<TActual>(TActual actual)
    {
        var actualTypeName = actual?.GetType().FullName;
        return new ConstraintResult(this, actualTypeName, actualTypeName == expectedFullTypeName);
    }
}

public class Is : NUnit.Framework.Is
{
    public static FullTypeNameConstraint FullTypeNameOf(string expectedFullTypeName) => new FullTypeNameConstraint(expectedFullTypeName);
}   

public static class CustomConstraintExtensions
{
    public static FullTypeNameConstraint FullTypeNameOf(this ConstraintExpression expression, string expectedFullTypeName)
    {
        var constraint = new FullTypeNameConstraint(expectedFullTypeName);
        expression.Append(constraint);
        return constraint;
    }
}    
Run Code Online (Sandbox Code Playgroud)

然后你将能够执行以下操作:

Assert.Throws(Is.FullTypeNameOf("System.Text.Json.JsonReaderException"), () => JsonDocument.Parse(json).Dispose());
Run Code Online (Sandbox Code Playgroud)

但老实说我不会推荐它。

顺便说一句,JsonDocument它是一次性的,实际上需要进行处置以释放池内存以供重用。

演示小提琴在这里: https: //dotnetfiddle.net/0dLxeO