我还没有注意到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
?
答案 0 :(得分:9)
首先,我们来谈谈JToken
是什么。
JToken
是JObject
,JArray
,JProperty
和JValue
的抽象基类。JObject
是JProperty
个对象的集合。 JObject
无法容纳任何其他类型的JToken
。JProperty
是一个名称 - 值对。该名称始终为字符串,除了另一个JToken
之外,该值可以是任何类型JProperty
。JArray
是除JToken
之外的任何类型JProperty
个对象的数组。JValue
表示JSON原语值。它可以包含字符串,数字,布尔值,日期或null。请注意,JValue
是与所有其他JTokens一样的引用类型。以上课程旨在为JSON spec建模。
现在让我们谈谈你正在做什么以及你在哪里感到困惑。
在您的代码中,您首先要创建一个JObject。 JObject包含一个名为item
的JProperty。 item
的值是另一个JObject,它包含两个JProperties,称为foo
和bar
。这些JProperties的值都是包含字符串的JValues(分别为4
和42
)。
接下来,使用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";
答案 1 :(得分:1)
实际上JToken
有对其父级的引用(检查Parent
属性)
回到您的示例 - 在此行jToken = "5";
中,您正在创建新的JToken
(更具体地说,字符串被隐式转换为JValue
)。基本上它与jToken = new JValue("5");
相同所以变量jToken
现在指向全新的JValue
。这解释了为什么更改未反映在原始JObject
中
要修复您的示例,请使用:((JValue)jToken).Value = "5";