0

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

dbc
  • 104,963
  • 20
  • 228
  • 340
Alexey Yeltsov
  • 333
  • 2
  • 13

1 Answers1

0

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.

Evk
  • 98,527
  • 8
  • 141
  • 191
  • Ah I see. So no way to do this elegantly out of the box. – Alexey Yeltsov Oct 31 '22 at 20:10
  • Yes, it's kind of in .NET spirit to not allow something that doesn't make sense, while other languages might just "return null" in such cases. Has good and bad sides, but it's nice to have language/framework to be consistent in that sense. – Evk Oct 31 '22 at 20:14