![](/img/trans.png)
[英]Getting error Newtonsoft.Json.Linq.JProperty cannot have multiple values when adding JToken
[英]Getting the error “Cannot add or remove items from Newtonsoft.Json.Linq.JProperty” in Json.net
因此,我試圖通過將json對象讀取為JObject,刪除一些字段,然后使用Json.Net將其反序列化為我的目標對象,來控制反序列化 。 問題是,每當我嘗試刪除字段時,都會收到錯誤消息:
Newtonsoft.Json.dll中發生了類型為'Newtonsoft.Json.JsonException'的未處理異常
附加信息:無法從Newtonsoft.Json.Linq.JProperty添加或刪除項目。
這是我的代碼(已簡化,但仍會導致錯誤):
JToken token = (JToken)JsonConvert.DeserializeObject(File.ReadAllText(fileName));
foreach (JToken inner in token["docs"])
{
if (inner["_id"] != null)
inner["_id"].Remove();
MyObject read = new MyObject();
JsonConvert.PopulateObject(inner.ToString(), read);
Values.Add((MyObject)JsonConvert.DeserializeObject(inner.ToString(), typeof(MyObject)));
}
json是一個非常大的文件,其中docs數組包含許多元素,如下所示(為簡化起見,再次簡化):
{
"docs": [
{
"Time": "None",
"Level": 1,
"_id": "10208"
},
{
"Time": "None",
"Level": 1,
"_id": "10209"
}
]
}
另外,如果有更好的方法將JSON反序列化為特定類型,但仍然忽略其他字段,那將是一個很好的選擇。
假定Values
是一個List<MyObject>
並且您的MyObject
類如下所示:
class MyObject
{
public string Time { get; set; }
public int Level { get; set; }
}
您可以將所有代碼替換為以下代碼,以獲得所需的結果:
string json = File.ReadAllText(fileName);
Values = JToken.Parse(json)["docs"].ToObject<List<MyObject>>();
之所以可行,是因為Json.Net默認會忽略缺少的屬性。 由於MyObject
類不包含要反序列化的_id
屬性,因此您無需跳過試圖將其從JSON中刪除的箍。
解釋為什么Remove()
不起作用
JToken.Remove()
從其父級移除JToken
。 它是合法的刪除JProperty
從其父JObject
,或刪除一個孩子JToken
從JArray
。 但是,您不能從JProperty
刪除該值。 JProperty
必須始終僅具有一個值。
當您請求token["_id"]
您將獲得稱為_id
的JProperty
的值 ,而不是JProperty
本身。 因此,如果您嘗試對該值調用Remove()
,則會收到錯誤消息。 要使其按照您的方式工作,您需要像這樣使用Parent
:
if (inner["_id"] != null)
inner["_id"].Parent.Remove();
這說:“查找名稱為_id
的屬性,並給我值。如果存在,請獲取該值的父級(屬性),並將其從其父級(包含JObject
)中JObject
。”
一種更直接的方法是使用Property()
方法直接訪問該屬性。 但是,此方法僅在JObject
上JObject
,而在JObject
不可JToken
,因此您需要將inner
的聲明更改為JObject
或將其JObject
為:
foreach (JObject inner in token["docs"].Children<JObject>())
{
JProperty idProp = inner.Property("_id");
if (idProp != null)
idProp.Remove();
...
}
最后,如注釋中所述,如果您使用的是C#6或更高版本,則可以使用null條件運算符將代碼縮短一些:
inner.Property("_id")?.Remove();
根據Brian的brillian回答,您可以根據自己的情況簡單地執行以下操作:
var inner_id = inner["_id"] as JProperty;
if (inner_id != null)
inner_id.Remove();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.