c# - ¿Cómo puedo volcar() un objeto JOs de Newtonsoft en LinqPad?
json json.net (9)
En LinqPad, intentar llamar a .Dump()
en un JObject de Newtonsoft JObject
produce una excepción:
RuntimeBinderException: ''Newtonsoft.Json.Linq.JObject'' no contiene una definición para ''Dump''.
Esto funciona para casi todo lo demás en LinqPad. Me gustaría descubrir un método que descargue un objeto JOs de JObject
, al igual que otros objetos, mostrando nombres de propiedades, valores, etc.
Ya he descubierto cómo hacer que descargue la cadena JSON, pero me gustaría ver un objeto obtener salida en lugar de solo una cadena de texto.
Acabo de probar esto hoy con un objeto JObject, agregando la biblioteca JSON.NET a través de Nuget y obtengo datos estructurados (y sin errores) de data.Dump () donde los datos son un objeto JObject.
Es un método de extensión estática, por lo que puede llamarlo como un método estático:
LINQPad.Extensions.Dump(jObject);
Veo que esto sucede en algunos tipos cuando (supongo) el compilador no puede vincularse a la extensión por algún motivo.
Hay una publicación en el sitio de LinqPad y una publicación de blog sobre el uso de Dump()
con objetos dynamic
.
Puede intentar crear otra extensión Dump () que examine las propiedades de JObject
y crear un Diccionario que pueda JObject
de forma JObject
.
Algo así: (complete WAG basado en la definición de JObject):
var values = jObject.Properties.ToDictionary(p=>p.Name, p=>p.Value);
values.Dump();
por supuesto, podría agregar recursión para objetos anidados, etc .:
//Usage: GetProperties(jObject).Dump();
public static object GetProperties(object o)
{
JObject j = o as JObject;
if(j == null)
{
return o.ToString();
}
return j.Properties().ToDictionary(p=>p.Name,p=>GetProperties(p.Value));
}
Esto parece hacer el truco muy bien:
dynamic dyn = ... // parse some JSON or whatever
((JObject)dyn).Properties().ToDictionary(p=>p.Name, p=>p.Value).Dump();
Si tienes una lista, esto funciona:
dynamic[] dyns = ...
dyns.Cast<JObject>().Select(o => o.Properties().ToDictionary(p => p.Name, p => p.Value)).Dump();
Además, esto es útil si tienes un programa linqpad:
static class JsonNetDumper {
public static IEnumerable<IDictionary<string, object>> ToDumpable(this IEnumerable<object> rg) {
return rg.Cast<JObject>().Select(o => o.Properties().ToDictionary(p => p.Name, p => (object)p.Value));
}
}
Puedes usar esto así:
dynamic[] dyns = ...
dyns.ToDumpable().Dump();
Extendiendo la idea de rdavisau , se me ocurrió esto:
public static class ExtMethods
{
public static object Dumpable(this JToken t)
{
if(t is JObject)
{
var json = JsonConvert.SerializeObject(t);
return JsonConvert.DeserializeObject<ExpandoObject>(json);
}
else if(t is JArray)
{
return (t as JArray).Select(Dumpable);
}
else if(t is JValue)
{
return t.ToString();
}
else if(t is JProperty)
{
var p = (t as JProperty);
return new { Name=p.Name, Value=Dumpable(p.Value) };
}
else
{
throw new Exception("unexpected type: " + t.GetType().ToString());
}
}
public static JToken DumpPretty(this JToken t)
{
t.Dumpable().Dump();
return t;
}
}
public static object Dumpable(JToken t)
{
return t.Dumpable();
}
De esta manera también puede imprimir de forma bastante matrices y los resultados de sus consultas que no son JObjects.
Hay un visualizador escrito específicamente para este propósito.
Incluya el paquete NMyVision.LinqPad.JsonVisualizer
NMyVision.LinqPad.JsonVisualizer y llame a JsonVisualizer.DumpJson(jObject)
, y aparecerá una pestaña con una bonita vista de árbol pequeño.
Mi conjetura es que estás haciendo algo como esto:
dynamic foo = ...;
foo.Dump();
Los métodos de extensión (que es el Dump
) no funcionan con la escritura dinámica. Si utiliza:
object foo = ...;
foo.Dump();
entonces espero que "funcione" bien. Puede que no haga lo que realmente desea, porque las propiedades en JObject
no son las propiedades JSON, que se proporcionan de forma dinámica.
(Llamar al método de extensión explícitamente según D la respuesta de Stanley también funcionará, pero puede que le resulte más conveniente hacerlo como método de extensión).
EDITAR: Sospecho fuertemente que Dump
simplemente no le dará lo que quiere, dado que no sabe nada sobre Json.NET y probablemente no maneje objetos dinámicos de la forma en que (por ejemplo) lo haría el depurador. Probablemente sería mejor que escribieras tu propio método Dump
para recorrer las propiedades de JObject
y volcarlas de forma recursiva. Si aún espera encontrar algo fuera de la caja, probablemente debería buscar en la documentación de Json.NET en lugar de buscar en LINQPad, aunque no sé si encontrará algo.
Para cualquier persona que aterrice aquí y desee obtener una salida LINQPad bonita de una cadena JSON, deserializar a ExpandoObject
es un enfoque efectivo y funciona de forma recursiva en cualquier jerarquía que pueda haber en los datos:
JsonConvert.DeserializeObject<ExpandoObject>(myJSONString).Dump();
Extendiendo eso para cubrir la pregunta real, un método de extensión en JObject en este sentido haría el truco:
public static class ExtMethods
{
public static JObject DumpPretty(this JObject jo)
{
var jsonString = JsonConvert.SerializeObject(jo);
JsonConvert.DeserializeObject<ExpandoObject>(jsonString).Dump();
return jo; // return input in the spirit of LINQPad''s Dump() method.
}
}
No es el método más eficiente, pero para un uso rápido al excavar en LINQPad hará el truco.
Usando el nuevo ToDump
puede .Dump()
un JObject de Newtonsoft JObject
directamente.
Agregue este fragmento a la consulta My Extensions
LINQPad
static Object ToDump(Object input)
{
var json = input as JObject;
if (json != null)
return json.ToObject<ExpandoObject>();
return input;
}
También deberá agregar una referencia a Netwonsoft.Json
la misma manera que hizo para su consulta principal
JObject
realmente no tiene propiedades, es un montón de JArray
y JProperty
. Puede usar el método de extensión directamente como lo sugiere una respuesta anterior , o convertir la dinámica en object
y volcar. Pero es mejor que lo conviertas de nuevo a su representación JSON con .ToString()
y .ToString()
eso.
var data = JsonConvert.DeserializeObject(@"{...}");
LINQPad.Extensions.Dump(data); // gives JObject, JArray, etc
((object)data).Dump(); // gives JObject, JArray, etc
((string)data.ToString()).Dump(); // given the JSON string back again
Algo relacionado, encontré un método .DumpJson
, que convierte objetos normales en json cuando se vuelca. Lo menciono principalmente porque describe cómo escribir una extensión de Dump
personalizada.