c# json linq json.net

c# - JContainer, JObject, JToken y Linq confusión



json json.net (2)

Realmente no necesita preocuparse por JContainer en la mayoría de los casos. Está allí para ayudar a organizar y estructurar LINQ-to-JSON en código bien factorizado.

La jerarquía de JToken ve así:

JToken - abstract base class JContainer - abstract base class of JTokens that can contain other JTokens JArray - represents a JSON array (contains an ordered list of JTokens) JObject - represents a JSON object (contains a collection of JProperties) JProperty - represents a JSON property (a name/JToken pair inside a JObject) JValue - represents a primitive JSON value (string, number, boolean, null)

Así que ya ves, un objeto JObject es un JContainer , que es un JToken .

Aquí está la regla básica de oro:

  • Si sabe que tiene un objeto (denotado por llaves { y } en JSON), use JObject
  • Si sabe que tiene una matriz o lista (denotada entre corchetes [ y ] ), use JArray
  • Si sabes que tienes un valor primitivo, usa JValue
  • Si no sabe qué tipo de token tiene, o quiere poder manejar cualquiera de los anteriores de una manera general, use JToken . Luego, puede verificar su propiedad Type para determinar qué tipo de token es y emitirlo de manera apropiada.

Tengo problemas para entender cuándo usar JContainer , JObject y JToken . Entiendo por los "estándares" que JObject está compuesto por JProperties y que JToken es la clase abstracta básica para todos los tipos de JToken , pero no entiendo JContainer .

Estoy usando C # y acabo de comprar LinqPad Pro 5.

Tengo un origen de datos JSON en un archivo, así que estoy deserializando el contenido de ese archivo con éxito usando esta declaración:

string json; using (StreamReader reader = new StreamReader(@"myjsonfile.json")) { json = reader.ReadToEnd(); }

En ese momento, tomo el objeto de cadena JSON y lo deserializo a un objeto JObject (y este podría ser mi error. ¿Quizás necesito hacer que jsonWork un JToken o JContainer ?):

JObject jsonWork = (JObject)JsonConvert.DeserializeObject(json);

En mis datos JSON (la cadena representada por JSON), tengo tres objetos: el objeto de nivel superior es similar a este:

{ "Object1" : { ... }, "Object2" : { ... }, "Object3" : { ... } }

Cada objeto está compuesto de todo tipo de tokens (matrices, cadenas, otros objetos, etc.), por lo que es JSON dinámico. (Utilicé puntos suspensivos como marcadores de posición en lugar de enturbiar esta pregunta con gran cantidad de datos JSON).

Sin embargo, quiero procesar "Object1" , "Object2" y "Object3" separado utilizando LINQ. Entonces, idealmente, me gustaría algo como esto:

// these lines DO NOT work var jsonObject1 = jsonWork.Children()["Object1"] var jsonObject2 = jsonWork.Children()["Object2"] var jsonObject3 = jsonWork.Children()["Object3"]

Pero las líneas anteriores fallan.

Utilicé var arriba porque no tengo idea de qué tipo de objeto debería usar: JContainer , JObject o JToken ! Solo para que sepa lo que quiero hacer, una vez que las variables jsonObject# anteriores estén asignadas correctamente, me gustaría usar LINQ para consultar el JSON que contienen. Aquí hay un ejemplo muy simple:

var query = from p in jsonObject1 where p.Name == "Name1" select p

Por supuesto, mi LINQ finalmente filtrará las matrices JSON, objetos, cadenas, etc., en la variable jsonObject . Creo que una vez que me ponga en marcha, puedo usar LinqPad para ayudarme a filtrar el JSON utilizando LINQ.

Descubrí que si uso:

// this line WORKS var jsonObject1 = ((JObject)jsonWork).["Object1"];

Entonces obtengo un tipo de jsonObject1 en jsonObject1 . ¿Es este el enfoque correcto?

No tengo claro cuándo / por qué se usaría JContainer cuando parece que los objetos JToken y JObject funcionan bastante bien con LINQ. ¿Cuál es el propósito de JContainer ?


JContainer es una clase base para elementos JSON que tienen elementos secundarios. JObject , JArray , JProperty y JConstructor heredan de él.

Por ejemplo, el siguiente código:

(JObject)JsonConvert.DeserializeObject("[1, 2, 3]")

JContainer una JContainer InvalidCastException , pero si la JContainer a un JContainer , estaría bien.

Con respecto a su pregunta original, si sabe que tiene un objeto JSON en el nivel superior, puede usar:

var jsonWork = JObject.Parse(json); var jsonObject1 = o["Object1"];