JToken不是JObject的参考?

时间:2016-06-24 05:07:55

标签: json.net linqpad

我还没有注意到James Newton King撰写或谈到JToken is 的内容。我做了一个错误的假设,它以某种方式持有对JObject的引用。这不是这种情况,因为这些LINQPad语句演示了:

var json = @"
{
    ""item"": {
        ""foo"": ""4"",
        ""bar"": ""42""
    }
}
";

var jO = JObject.Parse(json);
var jToken = jO["item"]["foo"];

jToken = "5";

jO.ToString().Dump("jO");

jToken.Dump("jToken");

输出:

jO
{
  "item": {
    "foo": "4",
    "bar": "42"
  }
}

jToken
5 

不应该jO["item"]["foo"] == 5

2 个答案:

答案 0 :(得分:9)

首先,我们来谈谈JToken是什么。

  • JTokenJObjectJArrayJPropertyJValue的抽象基类。
  • JObjectJProperty个对象的集合。 JObject无法容纳任何其他类型的JToken
  • JProperty是一个名称 - 值对。该名称始终为字符串,除了另一个JToken之外,该值可以是任何类型JProperty
  • JArray是除JToken之外的任何类型JProperty个对象的数组。
  • JValue表示JSON原语值。它可以包含字符串,数字,布尔值,日期或null。请注意,JValue是与所有其他JTokens一样的引用类型。

以上课程旨在为JSON spec建模。

现在让我们谈谈你正在做什么以及你在哪里感到困惑。

在您的代码中,您首先要创建一个JObject。 JObject包含一个名为item的JProperty。 item的值是另一个JObject,它包含两个JProperties,称为foobar。这些JProperties的值都是包含字符串的JValues(分别为442)。

接下来,使用JToken索引器语法来获取对foo JProperty(包含字符串值4的JValue)的的引用,并指定引用您的jToken变量。注意这个变量的声明类型是JToken,即使这里的值的实际类型实际上是JValue。 (如果你做jToken.GetType().Name.Dump("jToken type")

,你可以看到这一点

到目前为止我?

好的,这是我认为你感到困惑的地方。 JToken提供隐式和显式转换,允许从各种.NET原语进行分配或转换。如果您执行的jToken = "5"jToken = new JValue("5")完全相同。因此,您所做的就是将jToken变量的引用(包含4的JValue)替换为对包含5的其他JValue的新引用。这显然对原始的JObject没有影响。

如果您尝试修改原始JValue的值,则需要将jToken强制转换为JValue,然后使用Value setter进行设置。

((JValue)jToken).Value = "5";

小提琴:https://dotnetfiddle.net/StIGxM

答案 1 :(得分:1)

实际上JToken有对其父级的引用(检查Parent属性) 回到您的示例 - 在此行jToken = "5";中,您正在创建新的JToken(更具体地说,字符串被隐式转换为JValue)。基本上它与jToken = new JValue("5");相同所以变量jToken现在指向全新的JValue。这解释了为什么更改未反映在原始JObject中 要修复您的示例,请使用:((JValue)jToken).Value = "5";