問題描述
所以我試圖通過將 json 對象作為 JObject 讀取,刪除一些字段,然后使用 Json.Net.問題是,每當(dāng)我嘗試刪除字段時,都會收到錯誤消息:
So I'm trying to control deserialization by reading a json object as a JObject, deleting some fields, and then deserializing it again to my target object using Json.Net. The problem is, any time I try to delete a field, I get the error:
Newtonsoft.Json.JsonException"類型的未處理異常發(fā)生在 Newtonsoft.Json.dll
An unhandled exception of type 'Newtonsoft.Json.JsonException' occurred in Newtonsoft.Json.dll
附加信息:無法添加或刪除項目Newtonsoft.Json.Linq.JProperty.
Additional information: Cannot add or remove items from Newtonsoft.Json.Linq.JProperty.
這是我的(簡化,但仍然導(dǎo)致錯誤)代碼:
Here's my (simplified, but still causing the error) code:
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 數(shù)組包含許多元素,如下所示(為清楚起見再次簡化):
The json is a very large file where the docs array contains many elements as follows (again simplified for clarity):
{
"docs": [
{
"Time": "None",
"Level": 1,
"_id": "10208"
},
{
"Time": "None",
"Level": 1,
"_id": "10209"
}
]
}
或者,如果有更好的方法將 JSON 反序列化為特定類型,但仍然忽略其他字段,那將是一個不錯的選擇.
Alternatively if there's a better way to deserialize JSON to a specific type, but still ignoring additional fields, that would be a fine alternative.
推薦答案
假設(shè) Values
是一個 List
和你的 MyObject
類看起來像這樣:
Assuming Values
is a List<MyObject>
and your MyObject
class looks like this:
class MyObject
{
public string Time { get; set; }
public int Level { get; set; }
}
您可以將所有代碼替換為以下代碼以獲得您想要的結(jié)果:
you can replace all that code with the following to get the result you want:
string json = File.ReadAllText(fileName);
Values = JToken.Parse(json)["docs"].ToObject<List<MyObject>>();
這是因為 Json.Net 默認(rèn)會忽略缺失的屬性.由于 MyObject
類不包含要反序列化的 _id
屬性,因此您無需費(fèi)力嘗試將其從 JSON 中刪除.
This works because Json.Net will ignore missing properties by default. Since the MyObject
class does not contain an _id
property to deserialize into, you don't need to jump through hoops trying to remove it from the JSON.
Remove()
不起作用的原因說明
Explanation of why Remove()
didn't work
JToken.Remove()
從其父級中刪除 JToken
.從其父 JObject
中刪除 JProperty
或從 JArray
中刪除子 JToken
是合法的.但是,您不能從 JProperty
中刪除該值.JProperty
必須始終只有一個值.
JToken.Remove()
removes a JToken
from its parent. It is legal to remove a JProperty
from its parent JObject
, or to remove a child JToken
from a JArray
. However, you cannot remove the value from a JProperty
. A JProperty
must always have exactly one value.
當(dāng)您請求 token["_id"]
時,您會返回名為 _id
的 JProperty
的 value>,而不是 JProperty
本身.因此,如果您嘗試對該值調(diào)用 Remove()
,您將收到錯誤消息.要使其按照您的方式工作,您需要像這樣使用 Parent
:
When you ask for token["_id"]
you get back the value of the JProperty
called _id
, not the JProperty
itself. Therefore you will get an error if you try to call Remove()
on that value. To make it work the way you are doing, you'd need to use Parent
like this:
if (inner["_id"] != null)
inner["_id"].Parent.Remove();
這表示找到名稱為 _id
的屬性并給我值.如果存在,獲取該值的父級(屬性),并將其從其父級(包含 JObject
)."
This says "Find the property whose name is _id
and give me the value. If it exists, get that value's parent (the property), and remove it from its parent (the containing JObject
)."
更直接的方法是使用 Property()
方法直接訪問屬性.但是,此方法僅適用于 JObject
,不適用于 JToken
,因此您需要將 inner
的聲明更改為 JObject
或強(qiáng)制轉(zhuǎn)換:
A more straightforward way to do it is to use the Property()
method to access the property directly. However, this method is only available on JObject
, not JToken
, so you would either need to change the declaration of inner
to a JObject
or cast it:
foreach (JObject inner in token["docs"].Children<JObject>())
{
JProperty idProp = inner.Property("_id");
if (idProp != null)
idProp.Remove();
...
}
最后,正如評論中提到的,如果您使用的是 C# 6 或更高版本,您可以使用空條件運(yùn)算符稍微縮短代碼:
Lastly, as mentioned in the comments, if you're using C# 6 or later you can shorten the code a bit using the null-conditional operator:
inner.Property("_id")?.Remove();
這篇關(guān)于收到錯誤“無法從 Newtonsoft.Json.Linq.JProperty 添加或刪除項目"在 Json.net 中的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!