1

I am trying to modify an in memory JsonNode instance. Minimal reproducible code is simply (.NET Fiddle):

        string jsonString =
            @"{
  ""Date"": ""2019-08-01T00:00:00"",
  ""Temperature"": 25,
  ""Summary"": ""Hot"",
  ""DatesAvailable"": [
    ""2019-08-01T00:00:00"",
    ""2019-08-02T00:00:00""
  ],
  ""TemperatureRanges"": {
      ""Cold"": {
          ""High"": 20,
          ""Low"": -10
      },
      ""Hot"": {
          ""High"": 60,
          ""Low"": 20
      }
  }
}
";
        JsonNode jDataSet = JsonNode.Parse(jsonString)!;
        var dataSet = jDataSet.AsObject();
        foreach (var entry in dataSet)
        {
            if (entry.Key == "TemperatureRanges")
            {
                entry.Value.AsObject().Remove("Hot");
            }
            else if (entry.Key == "Date")
            {
                dataSet.Remove(entry.Key); // boom !
            }
        }

Obviously this is the wrong approach (as seen with other structure here), how should I re-write the above code to handle removal of JsonNode in my case ?

Current code trigger:

System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
   at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
   at System.Collections.Generic.List`1.Enumerator.MoveNext()
   at System.Text.Json.JsonPropertyDictionary`1.GetEnumerator()+MoveNext()
   at Tests.UnitTest1.Test2() in C:\Users\malat\project\tests\Tests\UnitTest1.cs:line 43

Using:

> dotnet --version
6.0.408

Fundamentally my question is identical to this one but for JsonNode.

malat
  • 12,152
  • 13
  • 89
  • 158
  • "Obviously this is the wrong approach" - you don't actually make that obvious in the question. Rather than posting pseudocode, please post a [mcve] including whatever happens that you don't want to happen. – Jon Skeet Jun 07 '23 at 05:55
  • Your code doesn't throw any exceptions for me... can you clarify which version of .NET you're using? – Jon Skeet Jun 07 '23 at 06:14
  • I *assumed* it was obvious because it is working for [dict](https://stackoverflow.com/a/62844729/136285). – malat Jun 07 '23 at 06:58
  • Ah, I've figured it out. I hadn't spotted that your repro isn't actually a repro, because you've commented out the problematic line. I'd encourage you to uncomment that - I don't see the benefit in providing code that needs to be tweaked in order to reproduce the issue,. – Jon Skeet Jun 07 '23 at 07:06

1 Answers1

2

Three options present themselves:

  • Call ToList() to create a sequence to iterate over that won't be modified by calling Remove:

    foreach (var entry in dataSet.ToList())
    

    That's somewhat inefficient of course - whether that's a problem or not for you will depend on your app.

  • Don't do the removal in the loop, but keep a list of keys you want to remove after iterating over dataSet.

  • Don't bother keeping a list - just unconditionally call dataSet.Remove("Date") after the loop. (In your example at least, you know the key you want to remove - and Remove doesn't throw an exception if the key is missing anyway.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194