したがって、jsonオブジェクトをJObjectとして読み取り、いくつかのフィールドを削除し、次に Json.Net を使用してターゲットオブジェクトに再度逆シリアル化することで、逆シリアル化を制御しようとしています。問題は、フィールドを削除しようとするたびにエラーが発生することです。
タイプ 'Newtonsoft.Json.JsonException'の未処理の例外がNewtonsoft.Json.dllで発生しました
追加情報: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
には常に正確に1つの値が必要です。
_token["_id"]
_を要求すると、JProperty
自体ではなく、__id
_と呼ばれるJProperty
のvalueが返されます。したがって、その値に対してRemove()
を呼び出そうとすると、エラーが発生します。それをあなたがやっている方法で機能させるには、次のようにParent
を使用する必要があります:
_if (inner["_id"] != null)
inner["_id"].Parent.Remove();
_
これは、「名前が__id
_のプロパティを見つけて、値を指定します。存在する場合は、その値の親(プロパティ)を取得し、その親(それを含むJObject
)から削除します。」
より簡単な方法は、Property()
メソッドを使用してプロパティに直接アクセスすることです。ただし、このメソッドはJObject
ではなくJToken
でのみ使用できるため、inner
の宣言を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();
_