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

11

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

JsonElement values = JsonDocument.Parse(json).RootElement;

抛出了 System.Text.Json.JsonReaderException 异常,但我无法捕获此异常,因为指向该异常会导致错误。

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

我只是想了解一下,为什么可能会抛出实际上似乎并不存在的东西。

更新 #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)

更新 #2: 我去查看是否有我缺失的 NuGet 包。我在 NuGet 上找到了 System.Text.Json(尽管已经可访问,我仍在测试文件中成功使用了 System.Text.JsonSerializer)。我添加了它,现在我遇到了实际问题:它由于其保护级别而无法访问。
using System.Text.Json;

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

然而,这并没有直接解决我如何在Assert.Throws<System.Text.Json.JsonReaderException>中捕获它的问题。


你能提供一个堆栈跟踪和JSON示例吗?你删除了所有与 Newtonsoft.Json 相关的内容吗? - Pavel Anikhouski
你确定 JsonReaderException 在命名空间 System.Text.Json 下吗?我猜应该在 Newtonsoft.Json 命名空间下,请参考这个链接 - Shawn Xiao
JsonReaderExceptionNewtonsoft.Json 特定的异常。正如 @PavelAnikhouski 所提到的,您可能仍然对它有一些依赖关系。 - Eldar
@PavelAnikhouski,你认为这与Newtonsoft有关吗?即使是空字符串也可能是无效的JSON示例。 - Namiskuukkwl
3个回答

9
System.Text.Json.JsonReaderException目前为internal,这表示 Microsoft 可能会随时修改或删除此类型,而 System.Text.Json 的用户不应该依赖于该类作为公共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.

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

Assert.Throws(Is.InstanceOf<JsonException>(), () => JsonDocument.Parse(json).Dispose());

如果由于某种原因你必须断言抛出的特定异常类型,你可以利用 Assert.Throws() 返回抛出的异常来检查异常的完整类型名称。
Assert.AreEqual("System.Text.Json.JsonReaderException",
                Assert.Throws(Is.InstanceOf<JsonException>(), () => JsonDocument.Parse(json).Dispose()).GetType().FullName);

或者您可以使用 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;
    }
}    

然后您将能够做到:

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

但是,老实说我不建议这样做。

另外,JsonDocument 是可处理的,并且实际上需要被处理以释放池化内存以供重用。

这里有一个演示 fiddle:https://dotnetfiddle.net/0dLxeO


谢谢!非常好的答案! - Namiskuukkwl

1

对于 xUnit,可以使用 Assert.ThrowsAny<JsonException>(action)


-6
你可以将 Newtonsoft.Json.dll 添加到你的项目引用中,这样就可以解决你的问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接