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

9

26

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.

Puccoon answered 18/1, 2013 at 20:3 Comment(0)
W
30

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.

Wetzel answered 16/3, 2014 at 13:34 Comment(4)
Great solution! This plays the best with linqpads dump out of all answers so far.Laevo
For an extension to other JSON types, see https://mcmap.net/q/514163/-how-can-i-dump-a-newtonsoft-jobject-in-linqpadMulticellular
p.s., you can just use jo.ToObject<ExpandoObject>() instead of serializing/deserializing.Medellin
how about use funtion name Dump , instead of DumpPretty. i can use jo.Dump() !!Hydrosol
I
23

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));
}
Ibnsina answered 18/1, 2013 at 20:7 Comment(6)
Unfortunately that doesn't really solve the problem. This spit out a nested set of values, but doesn't show the property names, so you can't make heads or tails of it.Puccoon
The blog post is specific to ExpandoObject and the way it implements IDictionary<string, object>, I believe. It's possible that as JObject implements IDictionary<string, JToken> it will give a nice output, but it's not general dynamic object handling.Epicardium
@KenMason Then you can't use LinqPad's Dump() because that's how it works.Ibnsina
No... That's not how it works for a JObject from Newtonsoft. That's the whole point of this post. :)Puccoon
My point is that LinqPad's Dump() works (I presume) by using reflection to get the public properties, which some special handling for Collections, Dictionaries, etc.Ibnsina
(cont.) Dump() does not have special handling to look at a JObject's weakly-typed Properties collection to know how to pretty-print it.Ibnsina
E
8

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.

Epicardium answered 18/1, 2013 at 20:7 Comment(2)
Unfortunately that doesn't really solve the problem. This spit out a nested set of values, but doesn't show the property names, so you can't make heads or tails of it.Puccoon
@KenMason: Well that's calling the LINQPad Dump method. That's the bit of my answer saying that it may not do what you want... it's using the actual properties of the object, rather than the dynamic ones. I suspect you may not find any way of doing it exactly as you'd like - at least not out of the box. Both mine and D Stanley's answers are reasonable though (IMO) in terms of your actual question of how to use Dump... it's just that Dump doesn't do what you want.Epicardium
M
4

Update

The latest version of LINQPad automatically formats JSON.NET objects like JObject nicely (similar to the ExpandoObject in the accepted answer).

LINQPad screenshot

Original Answer

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.

JsonVisualizer Output

Maw answered 15/1, 2019 at 20:45 Comment(0)
R
2

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();
Russel answered 18/2, 2014 at 21:43 Comment(0)
M
2

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.

Multicellular answered 27/1, 2016 at 16:5 Comment(0)
E
1

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.

Elisavetpol answered 25/1, 2013 at 17:24 Comment(0)
I
1

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

Isola answered 14/11, 2017 at 15:7 Comment(0)
F
-1

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.

enter image description here

Fray answered 17/7, 2014 at 5:38 Comment(2)
The problem with this approach is that you don't get to see the keys, only the values.Tense
True - fit my purpose but not a solutionFray

© 2022 - 2024 — McMap. All rights reserved.