如何将JToken添加到JObject?

时间:2013-03-14 15:45:25

标签: c# json.net

我正在尝试使用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."

我实际上尝试了几种不同的方法,但似乎无法到达任何地方。在我的例子中,我真正想要做的是将新项添加到“fruit”。如果有更好的方法或更简单的库可供使用,请告诉我。

3 个答案:

答案 0 :(得分:118)

我认为你对JSON.Net中的内容感到困惑。

  • JToken是任何类型的JSON值的通用表示。它可以是字符串,对象,数组,属性等。
  • JProperty是与名称配对的单个JToken值。它只能添加到JObject,其值不能是另一个JProperty
  • JObjectJProperties的集合。它不能直接保留任何其他类型的JToken

在您的代码中,您试图将JObject(包含“香蕉”数据的数据)添加到已经具有值{{1}的JProperty(“橙色”)包含JObject)。如您所见,这将导致错误。

您真正想要做的是向{"colour":"orange","size":"large"}添加名为“banana”的JProperty,其中包含其他水果JObject。以下是修订后的代码:

JProperties

答案 1 :(得分:30)

TL; DR:您应该将一个JProperty添加到JObject。简单。索引查询返回一个JValue,因此请弄清楚如何获取JProperty:)

接受的答案似乎没有回答这个问题。如果我想在特定的一个之后专门添加JProperty怎么办?首先,让我们从真正让我头脑清醒的术语开始。

  • JToken =所有其他类型的母亲。它可以是A JValue,JProperty,JArray或JObject。这是为解析机制提供模块化设计。
  • JValue =任何Json值类型(string,int,boolean)。
  • JProperty =任何JValue或JContainer(见下文)与名称(标识符)配对。例如"name":"value"
  • JContainer =包含其他类型(JObject,JValue)的所有类型的母亲。
  • JObject =包含JProperties
  • 集合的JContainer类型
  • JArray =包含集合JValue或JContainer的JContainer类型。

现在,当您使用index []查询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);
    }
  }
}

答案 2 :(得分:5)

只需将 .First 添加到bananaToken即可:
foodJsonObj["food"]["fruit"]["orange"].Parent.AddAfterSelf(bananaToken .First );
.First 基本上超越 { ,使其成为 JProperty ,而不是 JToken 即可。

@Brian Rogers,谢谢,我忘记了.Parent。编辑