Experimenting with System.Text.Json, and not able to cleanly express chain of properties with optional early temination.
I want something like this
((JsonNode)node)?["a"]?["b"]?["c"]
Note, I'm not looking for workarounds (I can write some wrappers, extensions methods, etc). I want to understand if this my issue, doc issue, or framework bug.
Sample code:
JsonNode rootNode = JsonNode.Parse(@"{""p"": ""v""}");
// These work as expected
_ = rootNode["a"]; // Ok
// _ = rootNode["a"]["b"]; // System.NullReferenceException - expected
_ = rootNode["a"]?["b"]; // Ok - expected
_ = rootNode["p"]; // Ok - expected
// Now this does not work as expected
// Unexpected exception: The node must be of type 'JsonObject'
//_ = rootNode["p"]?["x"];
JsonNode p = rootNode["p"]; // Ok so far, p is not null
// Unexpected exception: The node must be of type 'JsonObject'
// How come? Doc says Item[String] Gets or sets the element with the specified property name. If the property is not found, null is returned.
JsonNode x = p["x"];
Exception:
System.InvalidOperationException
HResult=0x80131509
Message=The node must be of type 'JsonObject'.
Source=System.Text.Json
StackTrace:
at System.Text.Json.Nodes.JsonNode.AsObject()
at System.Text.Json.Nodes.JsonNode.get_Item(String propertyName)
at JTokenConditional.Program.Main(String[] args) in
Environment: .net 6, VS 2022
CodePudding user response:
Docs for the indexer you use state in the Exceptions section:
InvalidOperationException The current JsonNode is not a JsonObject
And it makes sense - you can only obtain a property of something than can have a properties in the first place - that is of JsonObject (any other subtype of JsonNode cannot have properties). However, you have a JsonValue here (string "v"), so trying to obtain a property of that throws exception as it should according to the docs. It would only return null if you try to obtain non-existing property of JsonObject.
So if you are going this route - you have to first check if JsonNode you have is actually JsonObject before trying to access an indexer, if you don't want a possibility of exception.