serialize newtonsoft net leer jobject create json.net linqpad

json.net - newtonsoft - JToken no es una referencia de JObject?



linq to json (2)

Todavía no me he dado cuenta de que James Newton King escribió o habló sobre lo que es JToken . He hecho la suposición incorrecta de que de alguna manera contiene una referencia a JObject . Este no es el caso ya que estas declaraciones de LINQPad demuestran:

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

La salida:

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

¿No debería jO["item"]["foo"] == 5 ?


En realidad, JToken tiene una referencia a su padre (ver propiedad Parent ).
Volviendo a su ejemplo, en esta línea jToken = "5"; está creando un nuevo JToken (para ser más específico, la cadena se convierte implícitamente en JValue ). Básicamente es lo mismo que jToken = new JValue("5"); Entonces, la variable jToken ahora apunta a un nuevo JValue . Esto explica por qué el cambio no se refleja en JObject original.
Para corregir su ejemplo, use: ((JValue)jToken).Value = "5";


Primero, hablemos de lo que es un JToken .

  • JToken es la clase base abstracta para JObject , JArray , JProperty y JValue .
  • JObject es una colección de objetos JProperty . Un JObject no puede contener ningún otro tipo de JToken .
  • JProperty es un par nombre-valor. El nombre siempre es una cadena, y el valor puede ser cualquier tipo de JToken excepto otro JProperty .
  • JArray es una matriz de objetos JToken de cualquier tipo excepto JProperty .
  • JValue representa un valor primitivo JSON. Puede contener una cadena, número, booleano, fecha o nulo. Tenga en cuenta que JValue es un tipo de referencia como todos los demás JTokens.

Las clases anteriores están destinadas a modelar la especificación JSON .

Ahora hablemos de lo que está haciendo y de dónde se confunde.

En su código, primero está creando un JObject. El JObject contiene un artículo llamado JProperty. El valor del item es otro JObject que contiene dos JProperties, llamadas foo y bar . Los valores de estas JProperties son ambos JValues ​​que contienen cadenas ( 4 y 42 , respectivamente).

A continuación, usa la sintaxis del indexador JToken para obtener una referencia al valor de foo JProperty (un JValue que contiene el valor de cadena 4 ) y asigne esa referencia a su variable jToken . Tenga en cuenta que el tipo declarado de esta variable es JToken, aunque el tipo real del valor aquí es de hecho JValue. (Puede ver esto si lo hace jToken.GetType().Name.Dump("jToken type") )

Conmigo hasta ahora?

OK, aquí es donde creo que te estás confundiendo. JToken proporciona conversiones implícitas y explícitas que permiten su asignación o conversión a varias primitivas .NET. Si haces jToken = "5" eso realmente significa lo mismo que jToken = new JValue("5") . Entonces, lo que ha hecho es reemplazar la referencia que tenía su variable jToken (al JValue que contiene 4 ) con una nueva referencia a un JValue diferente que contiene 5 . Obviamente, esto no tendrá ningún efecto en el JObject original.

Si está intentando modificar el valor del JValue original, debe convertir su jToken a JValue y luego usar el Value setter para establecerlo.

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

Fiddle: https://dotnetfiddle.net/StIGxM