2016-06-24 7 views
2

Ich habe noch nicht bemerkt, dass James Newton King schrieb oder sprach über was JTokenis. Ich habe die falsche Annahme gemacht, dass es irgendwie einen Verweis auf JObject enthält. Dies ist nicht der Fall, da die diese LINQPad Aussagen zeigen:JToken ist keine Referenz von JObject?

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"); 

Der Ausgang:

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

jToken 
5 

Sollte nicht jO["item"]["foo"] == 5?

Antwort

6

Lassen Sie uns zuerst darüber sprechen, was ein JToken ist.

  • JToken ist die abstrakte Basisklasse für JObject, JArray, JProperty und JValue.
  • JObject ist eine Sammlung von JProperty Objekte. Eine JObject kann keine andere Art von JToken halten.
  • JProperty ist ein Name-Wert-Paar. Der Name ist immer eine Zeichenkette, und der Wert kann eine beliebige Art von JToken mit Ausnahme einer anderen JProperty sein.
  • JArray ist ein Array von JToken Objekten aller Art außer JProperty.
  • JValue repräsentiert einen JSON-Grundelementwert. Es kann eine Zeichenfolge, eine Zahl, einen Booleschen Wert, ein Datum oder eine Null enthalten. Beachten Sie, dass JValue ein Referenztyp wie alle anderen JTokens ist.

Die obigen Klassen dienen zur Modellierung der JSON spec.

Jetzt reden wir darüber, was Sie tun und wo Sie verwirrt werden.

In Ihrem Code erstellen Sie zuerst ein JObject. Das JObject enthält eine JProperty namens item. Der Wert item ist ein weiteres JObject, das zwei JProperties mit den Namen foo und bar enthält. Die Werte dieser JProperties sind beide JValues, die Strings enthalten (4 bzw. 42).

Als nächstes verwenden Sie die JToken Indexer Syntax einen Verweis auf den Wert des foo JProperty (ein JValue, die den String-Wert enthält 4) zu erhalten, und weisen, dass der Bezug auf Ihre jToken Variable. Beachten Sie, dass der deklarierte Typ dieser Variablen JToken ist, obwohl der tatsächliche Typ des Werts tatsächlich JValue ist. (Sie können dies sehen, wenn Sie tun jToken.GetType().Name.Dump("jToken type"))

Mit mir so weit?

OK, hier ist, wo ich denke, dass Sie verwirrt werden. JToken bietet implizite und explizite Konvertierungen, mit denen es verschiedenen .NET-Primitiven zugewiesen oder in sie umgewandelt werden kann. Wenn Sie jToken = "5" tun, bedeutet das wirklich das Gleiche wie jToken = new JValue("5"). Sie haben also den Verweis ersetzt, den Ihre jToken Variable (mit dem JValue, der 4 enthält) durch einen neuen Verweis auf einen anderen JValue ersetzt, der 5 enthält. Dies hat natürlich keine Auswirkungen auf das ursprüngliche JObject.

Wenn Sie versuchen, den Wert des ursprünglichen JValue zu ändern, müssen Sie Ihren jToken in JValue umwandeln und dann den Value Setter verwenden, um ihn festzulegen.

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

Fiddle: https://dotnetfiddle.net/StIGxM

+1

James Newton König diese Dokumentation :) – rasx

+0

@rasx verwenden sollte: Warum? In diesem Fall unterscheidet sich der Fall von der Zuordnung eines Werts von einer Eigenschaft zu einer lokalen Variablen und das Ändern dieser Variablen in der Erwartung, dass die ursprüngliche Eigenschaft geändert wird. Sie ordnen den Wert dieser Variablen neu zu, Sie ändern nicht das Objekt, auf das sie verweist ... –

1

Eigentlich JToken hat einen Verweis auf seine Eltern (Check Parent Eigentum).
Zurück zu Ihrem Beispiel - in dieser Zeile jToken = "5"; erstellen Sie neue JToken (um genauer zu sein, Zeichenfolge implizit in JValue konvertiert wird). Grundsätzlich ist es das gleiche wie jToken = new JValue("5"); So Variable jToken zeigt jetzt auf brandneu JValue. Dies erklärt, warum sich die Änderung nicht im Original JObject widerspiegelt.
Um Ihr Beispiel Verwendung zu beheben: ((JValue)jToken).Value = "5";

Verwandte Themen