如何将一个JToken添加到一个JObject?

我试图从一些文本添加JSON对象到现有的使用JSON.Net的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."

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

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

  • JToken是任何types的JSON值的通用表示。 它可能是一个string,对象,数组,属性等
  • JProperty是与名称配对的单个JToken值。 它只能被添加到一个JObject ,它的值不能是另一个JProperty
  • JObjectJObject的集合。 它不能直接持有任何其他types的JToken

在你的代码中,你试图添加一个JObject (包含“banana”数据的JProperty )到已经有一个值的JProperty (“orange”)(一个JObject包含{"colour":"orange","size":"large"} )。 正如你所看到的,这将导致错误。

你真正想做的是添加一个JProperty称为“香蕉” JObject包含其他水果JProperties 。 这里是修改后的代码:

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

TL; DR:您应该将JProperty添加到JObject。 简单。 索引查询返回一个JValue,所以找出如何获得JProperty 🙂


接受的答案是不回答这个问题。 如果我想专门添加一个特定的JProperty? 首先,让我们从真正头脑发展的术语开始。

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

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

你实际上想要得到的是整个属性,然后根据需要添加另一个属性。 为此,您使用JOjbect.Property("name") ,然后创build您的愿望的另一个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); } } } 

只要join.First你的bananaToken应该做到这一点:
foodJsonObj["food"]["fruit"]["orange"].Parent.AddAfterSelf(bananaToken
.First基本上移过{使其成为JProperty而不是JToken

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