25

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

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

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

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

4

9 回答 9

30

对于任何想要从 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 中挖掘时快速使用,它可以解决问题。

于 2014-03-16T13:34:48.710 回答
21

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

LINQPad.Extensions.Dump(jObject);

当(我认为)编译器由于某种原因无法绑定到扩展时,我看到某些类型会发生这种情况。

在 LinqPad 的网站上有一篇文章和一篇关于使用对象Dump()dynamic博客文章。

您可以尝试创建另一个 Dump() 扩展来检查属性JObject并创建一个可以Dump漂亮地编辑的 Dictionary。

像这样的东西:(完整的 WAG 基于 JObject 的定义):

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));
}
于 2013-01-18T20:07:51.523 回答
7

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

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

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

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

那么我希望它会“工作”正常。不过,它可能无法满足您的实际需求 - 因为属性JObject不是动态提供的 JSON 属性。

(根据 D Stanley 的回答明确调用扩展方法也可以,但您可能会发现仍然将其作为扩展方法更方便。)

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

于 2013-01-18T20:07:21.197 回答
3

更新

最新版本的 LINQPad 会自动格式化 JSON.NET 对象JObject(类似于已接受答案中的 ExpandoObject)。

LINQPad 截图

原始答案

有一个专门为此目的编写的可视化工具。

包括NMyVision.LinqPad.JsonVisualizerNuGet 包和调用JsonVisualizer.DumpJson(jObject),将出现一个带有漂亮小树视图的选项卡。

JsonVisualizer 输出

于 2019-01-15T20:45:26.987 回答
2

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

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();
于 2014-02-18T21:43:49.870 回答
2

扩展rdavisau 的想法,我想出了这个:

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

这样,您还可以漂亮地打印不是 JObjects 的查询的数组和结果。

于 2016-01-27T16:05:58.927 回答
1

JObject没有真正的属性,它是一堆JArray垃圾JProperty您可以按照先前答案的建议直接使用扩展方法,也可以将动态转换为object并转储。但是你最好将它转换回它的 JSON 表示.ToString()并转储它。

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方法,它在转储时将普通对象转换为json。我提到它主要是因为它描述了如何编写自定义Dump扩展。

于 2013-01-25T17:24:38.083 回答
1

使用 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与主查询相同的引用

于 2017-11-14T15:07:02.503 回答
-1

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

在此处输入图像描述

于 2014-07-17T05:38:45.810 回答