请使用以下代码:
ResponseContentType
这可以按预期工作。现在检查以下代码:
JProperty toke = new JProperty("value", new JValue(50)); //toke.Value is 50
toke.Value.Replace(new JValue(20)); //toke.Value is 20
这也按预期工作,但有一个重要的细节。 val0不再是toke的JSON树的一部分,val1 是 JSON树的一部分;这意味着val0没有有效的父级,而val1没有。
现在拿这个代码。
JValue val0 = new JValue(50);
JProperty toke = new JProperty("value", val0); //toke.Value is 50
JValue val1 = new JValue(20);
toke.Value.Replace(val1); //toke.Value is 20
行为不同; val0 仍然是toke的JSON树的一部分,而val1则不是。现在val0有一个有效的父级,而val1没有。
这是一个重要的区别,如果您使用Newtonsoft JSON树来表示结构,并将JTokens作为引用存储到树中,引用结构的方式可以根据被替换的值而改变,这似乎是不正确的。
我的推理有什么缺陷吗?或者是行为不正确,我认为是这样吗?
答案 0 :(得分:1)
我认为你有一个有效点:Replace
应该替换令牌实例并正确设置父级,即使令牌具有相同的值。
如果属性值为JObject
并且您使用相同的JObject
替换它,则可以正常工作:
JObject obj1 = JObject.Parse(@"{ ""foo"" : 1 }");
JProperty prop = new JProperty("bar", obj1);
JObject obj2 = JObject.Parse(@"{ ""foo"" : 1 }");
prop.Value.Replace(obj2);
Console.WriteLine("obj1 parent is " +
(ReferenceEquals(obj1.Parent, prop) ? "prop" : "not prop")); // "not prop"
Console.WriteLine("obj2 parent is " +
(ReferenceEquals(obj2.Parent, prop) ? "prop" : "not prop")); // "prop"
然而,代码似乎是故意编写的,以JValues
的方式工作。在source code中,我们看到JToken.Replace()
调用JContainer.ReplaceItem()
,后者又调用SetItem()
。在JProperty
课程中,SetItem()
的实现方式如下:
internal override void SetItem(int index, JToken item)
{
if (index != 0)
{
throw new ArgumentOutOfRangeException();
}
if (IsTokenUnchanged(Value, item))
{
return;
}
if (Parent != null)
{
((JObject)Parent).InternalPropertyChanging(this);
}
base.SetItem(0, item);
if (Parent != null)
{
((JObject)Parent).InternalPropertyChanged(this);
}
}
您可以看到它检查值是否为"未更改",如果是,则返回而不执行任何操作。如果我们查看IsTokenUnchanged()
的实现,我们会看到:
internal static bool IsTokenUnchanged(JToken currentValue, JToken newValue)
{
JValue v1 = currentValue as JValue;
if (v1 != null)
{
// null will get turned into a JValue of type null
if (v1.Type == JTokenType.Null && newValue == null)
{
return true;
}
return v1.Equals(newValue);
}
return false;
}
因此,如果当前令牌是JValue
,它会检查它是否Equals
另一个令牌,否则会自动认为该令牌已更改。而Equals
JValue
当然是基于底层基元本身是否相等。
我不能说这个实施决定背后的原因,但似乎值得reporting an issue给作者。 "正确"我认为,修复是SetItem
使用ReferenceEquals(Value, item)
代替IsTokenUnchanged(Value, item)
。