如何在LinqPad中转储()一个Newtonsoft JObject?

时间:2013-01-18 20:03:40

标签: c# json linqpad json.net

在LinqPad中,尝试在Newtonsoft JSON.Net .Dump()上调用JObject会产生异常:

  

RuntimeBinderException:'Newtonsoft.Json.Linq.JObject'不包含'转储'的定义。

这适用于LinqPad中的其他几乎所有内容。我想找出一个方法,它将转储一个Newtonsoft JObject,就像其他对象一样,显示属性名称,值等。

我已经想出如何让它转储JSON字符串,但是我想看到一个对象得到输出而不仅仅是一个文本字符串。

9 个答案:

答案 0 :(得分:25)

对于那些希望从JSON字符串获得漂亮的LINQPad输出的人来说,反序列化为ExpandoObject是一种有效的方法,并且可以递归地向下运行在数据中的任何层次结构中:

JsonConvert.DeserializeObject<ExpandoObject>(myJSONString).Dump();

扩展它以涵盖实际问题,JObject上的这些行的扩展方法可以解决这个问题:

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.
    }
}

不是最有效的方法,但是为了在LINQPad中进行挖掘时快速使用它可以解决问题。

答案 1 :(得分:13)

这是一个静态扩展方法,因此您可以将其称为静态方法:

LINQPad.Extensions.Dump(jObject);

我发现当某些类型发生时(我认为)编译器由于某种原因无法绑定到扩展名。

LinqPad上有a post 关于将Dump()dynamic个对象一起使用的网站和a blog post

您可以尝试创建另一个Dump()扩展程序,该扩展程序会检查JObject的属性并创建可以 Dump的词典。

这样的事情:(根据JObject的定义完成WAG):

var values = jObject.Properties.ToDictionary(p=>p.Name, p=>p.Value);
values.Dump();

当然你可以为嵌套对象等添加递归:

//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));
}

答案 2 :(得分:5)

我的猜测是你正在做这样的事情:

dynamic foo = ...;
foo.Dump();

扩展方法(Dump是)不适用于动态类型。如果您使用:

object foo = ...;
foo.Dump();

然后我预计它会“正常”工作。它可能不会做你真正想要的 - 因为JObject上的属性不是动态提供的JSON属性。

(根据D Stanley的答案明确地调用扩展方法也会起作用,但你可能会发现它仍然作为扩展方法更方便。)

编辑:我强烈怀疑Dump只是不会给你你想要的东西,因为它对Json.NET一无所知并且可能无法处理动态对象(比方说)调试器的方式。您可能最好编写自己的Dump方法来迭代JObject的属性并以递归方式转储它们。如果您仍然希望找到开箱即用的东西,您应该查看Json.NET documentation而不是寻找LINQPad,尽管我不知道您是否会找到任何东西。

答案 3 :(得分:2)

扩展rdavisau's idea,我提出了这个问题:

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();
}

通过这种方式,您还可以打印出不是JObject的查询数组和查询结果。

答案 4 :(得分:1)

JObject实际上没有属性,它是一堆JArrayJProperty gunk。您可以按照a previous answer的建议直接使用扩展方法,也可以将动态转换为object并转储。但是你最好只用.ToString()将它转换回它的JSON表示并转储它。

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

有点相关,我确实遇到了.DumpJson method,它在转储时将普通对象转换为 json。我之所以提到它主要是因为它描述了如何编写自定义Dump扩展名。

答案 5 :(得分:1)

这似乎很好地解决了这个问题:

dynamic dyn = ... // parse some JSON or whatever
((JObject)dyn).Properties().ToDictionary(p=>p.Name, p=>p.Value).Dump();

如果您有列表,则可以:

dynamic[] dyns = ...
dyns.Cast<JObject>().Select(o => o.Properties().ToDictionary(p => p.Name, p => p.Value)).Dump();

此外,如果你有一个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));
  }
}

您可以这样使用:

dynamic[] dyns = ...
dyns.ToDumpable().Dump();

答案 6 :(得分:0)

使用LINQPad的新ToDump,您可以.Dump()直接使用Newtonsoft JSON.Net JObject

将此代码段添加到LINQPad的My Extensions查询

static Object ToDump(Object input)
{
    var json = input as JObject;
    if (json != null)
        return json.ToObject<ExpandoObject>();
    return input;
}

您还需要添加对Netwonsoft.Json的引用,与您对主查询的引用相同

答案 7 :(得分:0)

为此专门编写了a visualizer

包含NMyVision.LinqPad.JsonVisualizer NuGet包并调用JsonVisualizer.DumpJson(jObject),随即会出现一个带有漂亮的小树视图的选项卡。

JsonVisualizer Output

答案 8 :(得分:-1)

我今天刚刚尝试使用JObject,通过Nuget添加了JSON.NET库,我从data.Dump()获取结构化数据(并且没有错误),其中数据是JObject。

enter image description here