我尚未注意到詹姆斯·牛顿·金(James Newton King)撰写或谈到了 JToken
是。我做出了错误的假设,即它以某种方式对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
?
首先,让我们谈谈 JToken
是什么。
-
JToken
是JObject
,JArray
,JProperty
和JValue
的抽象基类。 -
JObject
是JProperty
对象的集合。JObject
不能容纳任何其他类型的JToken
。 -
JProperty
是名称值对。该名称始终是字符串,该值可以是任何类型的JToken
,除另一个JProperty
。 -
JArray
是JToken
的一个数组,除JProperty
外,任何种类的对象 -
JValue
代表JSON原始值。它可以包含一个字符串,数字,布尔值,日期或null。请注意,JValue
是类型类型,就像所有其他Jtokens一样。
上面的类旨在建模JSON规格
现在让我们谈谈您在做什么以及您在哪里感到困惑。
在您的代码中,您首先创建了一个职位。该职位包含一个称为item
的Jproperty。item
的值是另一个包含两个Jproperties的锻炼,称为foo
和bar
。这些Jproperties的值既包含字符串(分别为4
和42
)。
接下来,您使用jtoken索引语法获取foo
Jproperty的 value 的引用(包含字符串值4
的JVALUE),并将该引用分配给您的jToken
变量。请注意,该变量的声明类型是jtoken的,即使此处值的实际类型实际上是JVALUE。(如果您执行jToken.GetType().Name.Dump("jToken type")
,可以看到这一点)
到目前为止和我在一起?
好吧,这是我认为您感到困惑的地方。Jtoken提供了隐式和明确的转换,可以将其从分配或投入到各种.NET原始词。如果您执行jToken = "5"
,那确实与jToken = new JValue("5")
相同。因此,您所做的是用新的参考jToken
变量(到包含4
的JVALUE)的引用,并使用对包含5
的不同JVALUE的新引用。显然,这将对原始局面没有影响。
如果您要修改原始JValue的值,则需要将jToken
投射到JValue,然后使用Value
设置器将其设置为设置。
((JValue)jToken).Value = "5";
小提琴:https://dotnetfiddle.net/stigxm
实际上JToken
具有其父(检查Parent
属性)。
返回您的示例 - 在此行jToken = "5";
中,您正在创建新的JToken
(更具体地说,字符串被隐式转换为JValue
)。基本上,它与jToken = new JValue("5");
相同,因此可变jToken
现在指向全新的JValue
。这解释了为什么更改未反映在原始JObject
中。
要修复您的示例:((JValue)jToken).Value = "5";