JTokenをJObjectに追加するにはどうすればよいですか?


84

JSON.Netを使用して、あるテキストから既存のJSONファイルにJSONオブジェクトを追加しようとしています。たとえば、次のようなJSONデータがある場合:

  {
  "food": {
    "fruit": {
      "apple": {
        "colour": "red",
        "size": "small"
      },
      "orange": {
        "colour": "orange",
        "size": "large"
      }
    }
  }
}

私はこのようにこれをやろうとしてきました:

var foodJsonObj = JObject.Parse(jsonText);
var bananaJson = JObject.Parse(@"{ ""banana"" : { ""colour"": ""yellow"", ""size"": ""medium""}}");
var bananaToken = bananaJson as JToken;
foodJsonObj["food"]["fruit"]["orange"].AddAfterSelf(bananaToken);

しかし、これはエラーを引き起こします: "Newtonsoft.Json.Linq.JProperty cannot have multiple values."

私は実際にいくつかの異なる方法を試しましたが、どこにも行けないようです。私の例では、私が本当にやりたいのは、新しいアイテムを「フルーツ」に追加することです。これを行うためのより良い方法または使用するより簡単なライブラリがあるかどうかを教えてください。

回答:


139

JSON.Netで何を保持できるかについて混乱していると思います。

  • AJTokenは、あらゆる種類のJSON値の一般的な表現です。文字列、オブジェクト、配列、プロパティなどが考えられます。
  • AJPropertyは、JToken名前とペアになった単一の値です。にのみ追加できJObject、その値を別の値にすることはできませんJProperty
  • AJObjectはのコレクションですJProperties。他の種類をJToken直接保持することはできません。

あなたのコードでは、すでに値(を含む)を持っている(「オレンジ」)に(「JObjectバナナ」データを含むもの)を追加しようとしJPropertyています。ご覧のとおり、これはエラーになります。JObject{"colour":"orange","size":"large"}

あなたが本当にやりたいのは、他の果物を含むJProperty「バナナ」と呼ばれるものを追加することです。改訂されたコードは次のとおりです。JObjectJProperties

JObject foodJsonObj = JObject.Parse(jsonText);
JObject fruits = foodJsonObj["food"]["fruit"] as JObject;
fruits.Add("banana", JObject.Parse(@"{""colour"":""yellow"",""size"":""medium""}"));

7
注:JObject.Parse最後の行では、の代わりに「JToken.Parse」(または「JToken.FromObject」)を使用してください。これは文字列などの単純なオブジェクトでも機能するためです。
ctrl-alt-delor 2014年

Jpropertyを上書きしたい場合はどうすればよいですか。
ダニエル

@ Daniel-「上書き」とは、を完全にJProperty別のものに置き換えることを意味する場合は、このReplaceメソッドを使用できます。の値を変更したいだけの場合はJPropertyValueプロパティを設定できます。書き込み可能です。参照してくださいLINQツーJSON APIリファレンスを
ブライアンロジャース

35

TL; DR:JPropertyをJObjectに追加する必要があります。シンプル。インデックスクエリはJValueを返すので、代わりにJPropertyを取得する方法を理解してください:)


受け入れられた答えは、見た目どおりに質問に答えていません。特定のJPropertyの後にJPropertyを具体的に追加したい場合はどうすればよいですか?まず、頭を悩ませた用語から始めましょう。

  • JToken =他のすべてのタイプの母。JValue、JProperty、JArray、またはJObjectにすることができます。これは、解析メカニズムにモジュラー設計を提供するためです。
  • JValue =任意のJson値タイプ(string、int、boolean)。
  • JProperty =名前(識別子)とペアになった任意のJValueまたはJContainer(以下を参照。たとえば"name":"value"
  • JContainer =他のタイプ(JObject、JValue)を含むすべてのタイプの母。
  • JObject = JPropertiesのコレクションを保持するJContainerタイプ
  • JArray =コレクションJValueまたはJContainerを保持するJContainerタイプ。

これで、インデックス[]を使用してJsonアイテムをクエリすると、識別子のないJTokenが取得されます。これはJContainerまたはJValue(キャストが必要)の場合がありますが、値にすぎないため、その後に何も追加できません。それ自体を変更したり、より深い値をクエリしたりすることはできますが、たとえば、その後に何も追加することはできません。

実際に取得したいのはプロパティ全体であり、必要に応じてその後に別のプロパティを追加します。このために、を使用しJOjbect.Property("name")、次に希望の別のJPropertyを作成し、この後にAddAfterSelfメソッドを使用して追加します。これで完了です。

詳細については、http//www.newtonsoft.com/json/help/html/ModifyJson.htmをご覧ください。

これは私が変更したコードです。

public class Program
{
  public static void Main()
  {
    try
    {
      string jsonText = @"
      {
        ""food"": {
          ""fruit"": {
            ""apple"": {
              ""colour"": ""red"",
              ""size"": ""small""
            },
            ""orange"": {
              ""colour"": ""orange"",
              ""size"": ""large""
            }
          }
        }
      }";

      var foodJsonObj = JObject.Parse(jsonText);
      var bananaJson = JObject.Parse(@"{ ""banana"" : { ""colour"": ""yellow"", ""size"": ""medium""}}");

      var fruitJObject = foodJsonObj["food"]["fruit"] as JObject;
      fruitJObject.Property("orange").AddAfterSelf(new JProperty("banana", fruitJObject));

      Console.WriteLine(foodJsonObj.ToString());
    }
    catch (Exception ex)
    {
      Console.WriteLine(ex.GetType().Name + ": " + ex.Message);
    }
  }
}

4
用語が間違っています。 JToken(ないJValueから基底クラスである)JArrayJObjectJProperty及びJValue最終的に継承。 JValue文字列、数値、ブール値、日付、またはnull値を表すJSONプリミティブです。配列やオブジェクトを表すことはできません。参照してくださいLINQツーJSON APIリファレンスを
ブライアンロジャース

1
@BrianRogersありがとう、用語を修正しました。
ガサン2015

1
これはNewtonsoftオブジェクトモデルの非常に良い説明であり、newtonsoft.com / json / help / html /N_Newtonsoft_Json_Linq.htmをよりよく理解できるようになりました。これまで、それを使用するための私の努力は、ドキュメントに詳細な説明がないために妨げられてきました。これは、コードコメントから自動生成された参照のようです。
トムウィルソン

2
ただし、コード例modは完全には正しくありません。 `var foodJsonObj = JObject.Parse(jsonText); var bananaJson = JObject.Parse(@ "{" "colour" ":" "yellow" "、" "size" ":" "medium" "}"); var FruitJObject = foodJsonObj ["food"] ["fruit"] as JObject; FruitJObject.Property( "orange")。AddAfterSelf(new JProperty( "banana"、bananaJson)); `
トムウィルソン

以前のコメントにコードマークアップを適用することはできません-AARRGHH!バックティックとインデントされた4つのスペースを使用しました-どうすればよいですか?
トムウィルソン

5

.Firstあなたに追加するだけでbananaTokenそれを行う必要があります:基本的にはを超えて移動し、の代わりになります。
foodJsonObj["food"]["fruit"]["orange"].Parent.AddAfterSelf(bananaToken .First);
.First{JPropertyJToken

@ブライアンロジャース、ありがとう私は忘れました.Parent。編集済み

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.