C# 如何将 JToken 添加到 JObject?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15413825/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 16:45:02  来源:igfitidea点击:

How do you add a JToken to an JObject?

c#json.net

提问by Jim

I'm trying to add a JSON object from some text to an existing JSON file using JSON.Net. For example if I have the JSON data as below:

我正在尝试使用 JSON.Net 将一些文本中的 JSON 对象添加到现有的 JSON 文件中。例如,如果我有如下的 JSON 数据:

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

I've been trying to do this like this:

我一直在尝试这样做:

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

But this gives the error: "Newtonsoft.Json.Linq.JProperty cannot have multiple values."

但这给出了错误: "Newtonsoft.Json.Linq.JProperty cannot have multiple values."

I've actually tried a few different ways but can't seem to get anywhere. In my example what I really want to do is add the new item to "fruit". Please let me know if there is a better way of doing this or a simpler library to use.

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

回答by Brian Rogers

I think you're getting confused about what can hold what in JSON.Net.

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

  • A JTokenis a generic representation of a JSON value of any kind. It could be a string, object, array, property, etc.
  • A JPropertyis a single JTokenvalue paired with a name. It can only be added to a JObject, and its value cannot be another JProperty.
  • A JObjectis a collection of JProperties. It cannot hold any other kind of JTokendirectly.
  • AJToken是任何类型的 JSON 值的通用表示。它可以是字符串、对象、数组、属性等。
  • AJPropertyJToken与名称配对的单个值。它只能添加到 a JObject,其值不能是 another JProperty
  • AJObject是 的集合JProperties。它不能JToken直接容纳任何其他类型。

In your code, you are attempting to add a JObject(the one containing the "banana" data) to a JProperty("orange") which already has a value (a JObjectcontaining {"colour":"orange","size":"large"}). As you saw, this will result in an error.

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

What you really want to do is add a JPropertycalled "banana" to the JObjectwhich contains the other fruit JProperties. Here is the revised code:

您真正想要做的是JPropertyJObject包含其他水果的 中添加一个名为“香蕉”的内容JProperties。这是修改后的代码:

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

回答by RepDbg

Just adding .Firstto your bananaTokenshould do it:
foodJsonObj["food"]["fruit"]["orange"].Parent.AddAfterSelf(bananaToken.First);
.Firstbasically moves past the {to make it a JPropertyinstead of a JToken.

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

@Brian Rogers, Thanks I forgot the .Parent. Edited

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

回答by Ghasan

TL;DR: You should add a JProperty to a JObject. Simple. The index query returns a JValue, so figure out how to get the JProperty instead :)

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



The accepted answer is not answering the question as it seems. What if I want to specifically add a JProperty after a specific one? First, lets start with terminologies which really had my head worked up.

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

  • JToken = The mother of all other types. It can be A JValue, JProperty, JArray, or JObject. This is to provide a modular design to the parsing mechanism.
  • JValue = any Json value type (string, int, boolean).
  • JProperty = any JValue or JContainer (see below) paired with a name (identifier). For example "name":"value".
  • JContainer = The mother of all types which contain other types (JObject, JValue).
  • JObject = a JContainer type that holds a collection of JProperties
  • JArray = a JContainer type that holds a collection JValue or JContainer.
  • JToken = 所有其他类型之母。它可以是 JValue、JProperty、JArray 或 JObject。这是为解析机制提供模块化设计。
  • JValue = 任何 Json 值类型(字符串、整数、布尔值)。
  • JProperty = 与名称(标识符)配对的任何 JValue 或 JContainer(见下文。例如"name":"value"
  • JContainer = 包含其他类型(JObject、JValue)的所有类型之母。
  • JObject = 包含 JProperties 集合的 JContainer 类型
  • JArray = 包含集合 JValue 或 JContainer 的 JContainer 类型。

Now, when you query Json item using the index [], you are getting the JToken without the identifier, which might be a JContainer or a JValue (requires casting), but you cannot add anything after it, because it is only a value. You can change it itself, query more deep values, but you cannot add anything after it for example.

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

What you actually want to get is the property as whole, and then add another property after it as desired. For this, you use JOjbect.Property("name"), and then create another JProperty of your desire and then add it after this using AddAfterSelfmethod. You are done then.

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

For more info: http://www.newtonsoft.com/json/help/html/ModifyJson.htm

更多信息:http: //www.newtonsoft.com/json/help/html/ModifyJson.htm

This is the code I modified.

这是我修改的代码。

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