问题
In LinqPad, trying to call .Dump()
on a Newtonsoft JSON.Net JObject
yields an exception:
RuntimeBinderException: 'Newtonsoft.Json.Linq.JObject' does not contain a definition for 'Dump'.
This works for almost everything else in LinqPad. I'd like to figure out a method that will Dump out a Newtonsoft JObject
, just like other objects, showing property names, values, etc.
I've already figured out how to get it to dump the JSON string, but I'd like to see an object get output rather than just a text string.
回答1:
For anyone who lands here wanting to get pretty LINQPad output from a JSON string, deserializing to ExpandoObject
is an effective approach and works recursively down any hierarchies that may be in the data:
JsonConvert.DeserializeObject<ExpandoObject>(myJSONString).Dump();
Extending that to cover the actual question, an extension method on JObject along these lines would do the trick:
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.
}
}
Not the most efficient method, but for quick use when digging around in LINQPad it will do the trick.
回答2:
It's a static extension method, so you can call it as a static method:
LINQPad.Extensions.Dump(jObject);
I see that happen on some types when (I presume) the compiler isn't able to bind to the extension for some reason.
There's a post on LinqPad
's site and a blog post regarding using Dump()
with dynamic
objects.
You might try creating another Dump() extension that examines the properties of JObject
and creating a Dictionary that can be Dump
ed prettily.
Something like this: (complete WAG based on JObject's definition):
var values = jObject.Properties.ToDictionary(p=>p.Name, p=>p.Value);
values.Dump();
of course you could add recursion for nested objects, 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));
}
回答3:
My guess is that you're doing something like this:
dynamic foo = ...;
foo.Dump();
Extension methods (which Dump
is) don't work with dynamic typing. If you use:
object foo = ...;
foo.Dump();
then I expect it will "work" fine. It may well not do what you actually want though - because the properties on JObject
aren't the JSON properties, which are provided dynamically.
(Calling the extension method explicitly as per D Stanley's answer will work too, but you may find it more convenient to still do it as an extension method.)
EDIT: I strongly suspect that Dump
simply won't give you what you want, given that it doesn't know anything about Json.NET and probably doesn't handle dynamic objects in the way that (say) the debugger would. You'd probably be best off writing your own Dump
method to iterate over the properties of the JObject
and dump them recursively. If you're still hoping to find something out of the box, you should probably look in the Json.NET documentation rather than looking to LINQPad, although I don't know whether you'll find anything.
回答4:
Extending rdavisau's idea, I came up with this:
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();
}
This way you can also pretty-print arrays and results of your queries which are not JObjects.
回答5:
JObject
doesn't really have properties, it's a bunch of JArray
and JProperty
gunk. You can either use the extension method directly as suggested by a previous answer, or cast the dynamic to object
and dump. But you're better off just converting it back to it's JSON representation with .ToString()
and dumping that.
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
Somewhat related, I did come across a .DumpJson method, which turns normal objects into json when dumping. I mention it mostly because it describes how to write a custom Dump
extension.
回答6:
This seems to do the trick nicely:
dynamic dyn = ... // parse some JSON or whatever
((JObject)dyn).Properties().ToDictionary(p=>p.Name, p=>p.Value).Dump();
If you have a list, this works:
dynamic[] dyns = ...
dyns.Cast<JObject>().Select(o => o.Properties().ToDictionary(p => p.Name, p => p.Value)).Dump();
Also, this is handy if you've got a linqpad program:
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));
}
}
You can use this like so:
dynamic[] dyns = ...
dyns.ToDumpable().Dump();
回答7:
Using LINQPad's new ToDump you can .Dump()
a Newtonsoft JSON.Net JObject
directly.
Add this snippet to LINQPad's My Extensions
query
static Object ToDump(Object input)
{
var json = input as JObject;
if (json != null)
return json.ToObject<ExpandoObject>();
return input;
}
You will also need to add a reference to Netwonsoft.Json
the same as you did for your main query
回答8:
There's a visualizer written specifically for this purpose.
Include the NMyVision.LinqPad.JsonVisualizer
NuGet package and call JsonVisualizer.DumpJson(jObject)
, and a tab will appear with a nice little tree view.
回答9:
I've just tried this today with a JObject, having added the JSON.NET library via Nuget and I get structured data back (and no errors) from data.Dump() where data is a JObject.
来源:https://stackoverflow.com/questions/14406769/how-can-i-dump-a-newtonsoft-jobject-in-linqpad