如何正确移除JsonNode?解决枚举修改集合异常
遍历JsonNode对象时移除元素的正确写法
在.NET 6中遍历JsonNode解析得到的JsonObject时,直接在循环内移除元素会触发InvalidOperationException——这是因为枚举集合的过程中,不允许修改集合本身的结构(添加/删除元素)。
复现代码
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); // 此处触发异常 } }
异常信息
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
使用的.NET版本
> dotnet --version 6.0.408
解决方法
和普通集合的处理逻辑一致,核心是避免在枚举原集合的同时修改它,以下两种方法都可以解决问题:
方法1:先收集待删除的键,再批量移除
先遍历一次集合,把需要删除的键存到一个独立列表里,再遍历这个列表执行删除操作:
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(); // 第一步:收集所有需要删除的键 var keysToRemove = new List<string>(); foreach (var entry in dataSet) { if (entry.Key == "TemperatureRanges") { // 子对象的修改不影响当前集合枚举,可直接操作 entry.Value.AsObject().Remove("Hot"); } else if (entry.Key == "Date") { keysToRemove.Add(entry.Key); } } // 第二步:批量删除 foreach (var key in keysToRemove) { dataSet.Remove(key); }
方法2:反向遍历索引
把集合的键转成列表后,从最后一个元素往前遍历,这样删除元素不会影响后续遍历的索引位置:
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(); // 把键转成列表,避免枚举时集合变化 var keys = dataSet.Keys.ToList(); // 从后往前遍历索引 for (int i = keys.Count - 1; i >= 0; i--) { var key = keys[i]; if (key == "TemperatureRanges") { dataSet[key].AsObject().Remove("Hot"); } else if (key == "Date") { dataSet.Remove(key); } }
内容的提问来源于stack exchange,提问作者malat
相关产品推荐
相关产品推荐

