问题描述
我还没有注意到James Newton King撰写或谈论了JToken
是 .我做出了一个错误的假设,即它以某种方式保留了对JObject
的引用.这些LINQPad语句演示的情况并非如此:
I have not yet noticed that James Newton King wrote or spoke about what JToken
is. I have made the incorrect assumption that it somehow holds a reference to JObject
. This is not the case as the these LINQPad statements demonstrate:
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
是.
First, let's talk about what a JToken
is.
-
JToken
是JObject
,JArray
,JProperty
和JValue
的抽象基类. -
JObject
是JProperty
对象的集合.JObject
不能容纳任何其他种类的JToken
. -
JProperty
是一个名称/值对.名称始终是一个字符串,值可以是任何JToken
,除了另一个JProperty
. -
JArray
是除JProperty
之外的任何类型的JToken
对象的数组. -
JValue
表示JSON基本值.它可以包含字符串,数字,布尔值,日期或null.请注意,JValue
是与所有其他JTokens一样的引用类型.
JToken
is the abstract base class forJObject
,JArray
,JProperty
andJValue
.JObject
is a collection ofJProperty
objects. AJObject
cannot hold any other kind ofJToken
.JProperty
is a name-value pair. The name is always a string, and the value can be any kind ofJToken
except anotherJProperty
.JArray
is an array ofJToken
objects of any kind exceptJProperty
.JValue
represents a JSON primitive value. It can contain a string, number, boolean, date or null. Note thatJValue
is a reference type like all other JTokens.
上述类旨在为 JSON规范建模.
现在让我们谈谈您在做什么以及感到困惑的地方.
Now let's talk about what you're doing and where you're getting confused.
在您的代码中,您首先要创建一个JObject. JObject包含一个称为item
的JProperty. item
的值是另一个JObject,它包含两个JProperty,分别称为foo
和bar
.这些JProperty的值都是包含字符串的JValue(分别为4
和42
).
In your code, you are first creating a JObject. The JObject contains one JProperty called item
. The value of item
is another JObject which contains two JProperties, called foo
and bar
. The values of these JProperties are both JValues containing strings (4
and 42
, respectively).
接下来,您使用JToken索引器语法获取对foo
JProperty的 value 的引用(一个包含字符串值4
的JValue),并将该引用分配给您的jToken
变量.请注意,此变量的声明类型为JToken,即使该值的实际类型实际上是JValue. (如果您执行jToken.GetType().Name.Dump("jToken type")
,则可以看到此内容)
Next, you use the JToken indexer syntax to get a reference to the value of the foo
JProperty (a JValue which contains the string value 4
) and assign that reference to your jToken
variable. Note the declared type of this variable is JToken, even though the actual type of the value here is in fact JValue. (You can see this if you do jToken.GetType().Name.Dump("jToken type")
)
到目前为止和我在一起吗?
With me so far?
好的,这是我认为您感到困惑的地方. JToken提供隐式和显式转换,从而允许将其从各种.NET原语分配或强制转换为各种.NET原语.如果您执行jToken = "5"
,则实际上与jToken = new JValue("5")
含义相同.因此,您要做的是用对另一个包含5
的JValue的新引用替换您的jToken
变量具有的引用(对包含4
的JValue).这显然不会对原始JObject产生影响.
OK, here is where I think you are getting confused. JToken provides implicit and explicit conversions which allow it to be assigned from or cast to various .NET primitives. If you do jToken = "5"
that really means the same thing as jToken = new JValue("5")
. So what you have done is to replace the reference that your jToken
variable had (to the JValue containing 4
) with a new reference to a different JValue containing 5
. This obviously will have no effect on the original JObject.
如果尝试修改原始JValue的值,则需要将jToken
强制转换为JValue,然后使用Value
设置器进行设置.
If you are trying to modify the value of the original JValue, you need to cast your jToken
to JValue and then use the Value
setter to set it.
((JValue)jToken).Value = "5";
提琴: https://dotnetfiddle.net/StIGxM
这篇关于JToken不是JObject的引用吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!