C# 如何将JToken添加到作业对象?

C# 如何将JToken添加到作业对象?,c#,json.net,C#,Json.net,我正在尝试使用JSON.Net将一个JSON对象从一些文本添加到现有的JSON文件中。例如,如果我有如下JSON数据: { "food": { "fruit": { "apple": { "colour": "red", "size": "small" }, "orange": { "colour": "orange", "size": "large" } }

我正在尝试使用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不能有多个值。”


事实上,我试过几种不同的方法,但似乎都没有成功。在我的示例中,我真正想做的是将新项添加到“水果”中。请让我知道是否有更好的方法或更简单的库来使用

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

  • JToken
    是任何类型的JSON值的通用表示。它可以是字符串、对象、数组、属性等
  • JProperty
    是一个与名称成对的
    JToken
    值。它只能添加到
    JObject
    ,其值不能是另一个
    JProperty
  • JObject
    jproperty
    的集合。它不能直接持有任何其他类型的
    JToken
在代码中,您试图将
JObject
(包含“香蕉”数据的对象)添加到
JProperty
(“橙色”)中,该属性已具有值(包含
{“颜色”:“橙色”,“大小”:“大”}
)。如您所见,这将导致错误

您真正想要做的是将名为“香蕉”的
JProperty添加到
JObject
中,该JObject包含其他水果
JProperty
。修订后的守则如下:

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

只需将
添加到您的
bananaToken
中即可:首先
foodJsonObj[“食品”][“水果”][“橙子”]。Parent.addafterelf(巴纳托肯
.First

.First
基本上通过
{
使其成为
而不是


@Brian Rogers,谢谢,我忘记了
.Parent
.Edited

TL;DR:您应该向JObject添加一个JProperty。很简单。索引查询返回一个JValue,因此请找出如何获取JProperty:)


公认的答案似乎并没有回答这个问题。如果我想在一个特定的属性之后添加一个JProperty,该怎么办?首先,让我们从那些真正让我头疼的术语开始

  • JToken=所有其他类型的母亲。它可以是JValue、JProperty、JArray或JObject。这是为了为解析机制提供模块化设计
  • JValue=任何Json值类型(字符串、整型、布尔型)
  • JProperty=与名称(标识符)配对的任何JValue或JContainer(见下文)。例如
    “name”:“value”
  • JContainer=包含其他类型(JObject、JValue)的所有类型的母亲
  • JObject=保存JProperty集合的JContainer类型
  • JArray=保存集合JValue或JContainer的JContainer类型
现在,当您使用索引[]查询Json项时,您得到的JToken没有标识符,可能是JContainer或JValue(需要强制转换),但您不能在它后面添加任何内容,因为它只是一个值。您可以更改它本身,查询更深层的值,但不能在它后面添加任何内容,例如

实际上,您希望得到的是整个属性,然后根据需要在其后面添加另一个属性。为此,您可以使用
JOjbect.property(“name”)
,然后创建另一个您想要的JProperty,然后使用
AddAfterSelf
方法在此之后添加它。然后完成

有关更多信息:

这是我修改的代码

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);
    }
  }
}

注意:在最后一行使用“JToken.Parse”(或“JToken.FromObject”)而不是
JObject.Parse
。因为这也适用于字符串等简单对象。如果要覆盖Jproperty,该怎么办。@Daniel-如果使用“覆盖”您的意思是用另一个属性完全替换
JProperty
,然后可以使用
replace
方法。如果您只想更改
JProperty
的值,可以在其上设置
value
属性;它是可写的。请参阅。您的术语有误。
JToken
(不是
JValue
)是
JArray
JObject
JProperty
JValue
最终继承的基类。
JValue
是一个JSON原语,表示字符串、数字、布尔值、日期或空值;它不能表示数组或对象。请参阅。@BrianRogers谢谢,我修复了这个术语。这是一个对Newtonsoft对象模型的解释非常好,我现在能够更好地理解。到目前为止,由于文档中缺乏详细的解释,我使用它的努力受到了阻碍。它似乎只是根据代码注释自动生成的参考。但是,代码示例mod不太正确:`var foodJsonObj=JObject.Parse(jsonText);var bananaJson=JObject.Parse(“{”“color”“:”“yellow”“size”“:”“medium”“}”);var fruitJObject=foodJsonObj[“food”][“fruit”]作为JObject;fruitJObject.Property(“orange”).addafterlf(新的JProperty(“香蕉”,bananaJson))?