89

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

我实际上尝试了几种不同的方法,但似乎无处可去。在我的示例中,我真正想做的是将新项目添加到“水果”中。请让我知道是否有更好的方法或更简单的库来使用。

4

3 回答 3

146

我认为您对 JSON.Net 中可以保存的内容感到困惑。

  • AJToken是任何类型的 JSON 值的通用表示。它可以是字符串、对象、数组、属性等。
  • A是与名称配对JProperty的单个值。JToken它只能添加到 aJObject中,并且它的值不能是 another 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""}"));
于 2013-04-03T08:21:35.603 回答
39

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


接受的答案并没有像看起来那样回答问题。如果我想在特定的 JProperty 之后专门添加一个 JProperty 怎么办?首先,让我们从真正让我头疼的术语开始。

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

现在,当您使用索引 [] 查询 Json 项目时,您将获得不带标识符的 JToken,它可能是 JContainer 或 JValue(需要强制转换),但您不能在其后添加任何内容,因为它只是一个值。你可以自己改变它,查询更深的值,但是你不能在它之后添加任何东西。

您真正想要获得的是整个属性,然后根据需要在其后添加另一个属性。为此,您使用JOjbect.Property("name"),然后创建另一个您想要的 JProperty,然后在此 usingAddAfterSelf方法之后添加它。那你就完成了。

欲了解更多信息: 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);
    }
  }
}
于 2015-06-14T04:40:11.830 回答
5

只需添加.First到你bananaToken应该做的事情:基本上移动过去以使其成为 a而不是 a 。
foodJsonObj["food"]["fruit"]["orange"].Parent.AddAfterSelf(bananaToken .First);
.First{JPropertyJToken

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

于 2015-02-13T00:36:31.140 回答