Search code examples
jsonf#json.netjsonpath

Removing property with Json.NET using deep scan selector works with C# but throws ObjectNullReferenceException in F#


Using json.net 12.0.3 in an netcoreapp3.1 application, the code works fine from if written in C# and will work using dot-notation in F# but as soon as I try to remove an element found by a deep scan selector in F# it throw an object null reference exception. Given both are .NET languages my expectations would be for identical behavior. I could not find any documented differences or behavior expectations. Is there any possible resource other than not using F#?

Sample Document

{
  "Active": true,
    Nested: {
      "Active": true,
    }
}

Failing F# Code

let json = JObject.Parse(File.ReadAllText(@"c:\example.json"))
json.SelectTokens("..Active") 
|> Seq.iter (fun n -> n.Parent.Remove())

Succeeding C# Code

var json = JObject.Parse(File.ReadAllText(@"c:\example.json"));
json.SelectTokens("..Active").ToList().ForEach(i => i.Parent.Remove());

Solution

  • I'm not sure exactly where the NRE comes from, but there is one obvious difference between C# and F# versions: in C# you're converting to a list before iteration, but in F# you're not. Try doing that:

    let json = JObject.Parse(File.ReadAllText(@"c:\example.json"))
    json.SelectTokens("..Active") 
    |> List.ofSeq
    |> List.iter (fun n -> n.Parent.Remove())
    

    I would speculate that as you call Remove the contents of the sequence changes, yielding a null somewhere. But if you convert to a list beforehand, it's a snapshot of the sequence as it was before any removals were done.