How can I Dump() a Newtonsoft JObject in LinqPad?

↘锁芯ラ 提交于 2020-01-21 03:58:24

问题


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 Dumped 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!