Je convertis un projet .NET Framework 4.5 en .NET Core 3.1. Mes tests utilisaient Newtonsoft.Json pour vérifier si json est valide et maintenant je voudrais implémenter la même chose avec le System.Text.Json intégré. Il semble que
using System.Text.Json; namespace System.Text.Json { internal sealed class JsonReaderException : JsonException { public JsonReaderException(string message, long lineNumber, long bytePositionInLine); } }
jette System.Text.Json.JsonReaderException
, mais je ne peux pas l'attraper car pointer vers cette exception entraîne une erreur
Le type ou le nom d'espace de noms 'JsonReaderException' n'existe pas dans l'espace de noms 'System.Text.Json' (vous manquez une référence d'assembly?)
Je voudrais simplement comprendre comment est-il possible que quelque chose qui ne semble pas réellement exister puisse être jeté.
Mise à jour n ° 1: Stacktrace:
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)
Mise à jour n ° 2: Je suis allé voir s'il y aurait des pépites qui me manquaient. J'ai trouvé System.Text.Json en tant que nuget (bien qu'il soit déjà accessible, j'ai utilisé System.Text.JsonSerializer avec succès dans le fichier de test). Je l'ai ajouté et maintenant j'obtiens le problème réel: il est inaccessible en raison de son niveau de protection.
JsonElement values = JsonDocument.Parse(json).RootElement;
Cela ne résout cependant pas directement, comment puis-je attraper cela dans Assert.Throws<System.Text.Json.JsonReaderException>
?
3 Réponses :
Vous pouvez ajouter Newtonsoft.Json.dll
à vos références de projet pour résoudre votre problème.
Le fait que System.Text.Json.JsonReaderException
soit actuellement internal
indique que Microsoft peut modifier ou supprimer ce type à tout moment, et les utilisateurs de System.Text.Json
ne doivent pas dépendre de l'existence continue de cette classe en tant que sous-classe du public JsonException
. En effet, la documentation d' Utf8JsonReader
indique uniquement que
Lorsque
Utf8JsonReader
rencontre un JSON non valide, il lève uneJsonException
avec des informations d'erreur de base telles que le numéro de ligne et la position de l'octet sur la ligne.
Et les commentaires de code pour l'état JsonReaderException
:
Assert.Throws(Is.FullTypeNameOf("System.Text.Json.JsonReaderException"), () => JsonDocument.Parse(json).Dispose());
Au lieu de cela , affirmez que l'exception levée est une JsonException
en utilisant Is.InstanceOf<JsonException>()
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; } }
Si, pour une raison quelconque, vous devez affirmer le type d'exception spécifique qui a été levé, vous pouvez vérifier le nom de type complet de l'exception en tirant parti du fait que Assert.Throws()
renvoie l'exception levée:
Assert.AreEqual("System.Text.Json.JsonReaderException", Assert.Throws(Is.InstanceOf<JsonException>(), () => JsonDocument.Parse(json).Dispose()).GetType().FullName);
Ou vous pouvez utiliser le mécanisme de contrainte personnalisé de NUnit et introduire une FullTypeNameConstraint
comme suit:
Assert.Throws(Is.InstanceOf<JsonException>(), () => JsonDocument.Parse(json).Dispose());
Et puis vous pourrez faire:
// This class exists because the serializer needs to catch reader-originated exceptions in order to throw JsonException which has Path information.
Mais honnêtement, je ne le recommanderais pas.
En JsonDocument
, JsonDocument
est jetable et doit en fait être supprimé pour libérer de la mémoire en pool pour une réutilisation.
Démo violon ici: https://dotnetfiddle.net/0dLxeO .
Merci! Très bonne réponse!
Pour xUnit, on peut utiliser Assert.ThrowsAny<JsonException>(action)
Pouvez-vous une trace de pile et un échantillon json? Avez-vous supprimé tout ce qui concerne
Newtonsoft.Json
?Êtes-vous sûr que
JsonReaderException
trouve sous l'espace de nomsSystem.Text.Json
? Je suppose que cela devrait être sous l'Newtonsoft.Json
nomsNewtonsoft.Json
, veuillez vous référer à ce LIEN .JsonReaderException
est une exception spécifique àNewtonsoft.Json
. Vous devez toujours avoir des dépendances dessus, comme l'a mentionné @PavelAnikhouski.@PavelAnikhouski Pensez-vous toujours que cela pourrait être lié à Newtonsoft après ce stacktrace? Un exemple de json invalide serait une chaîne vide.