运行时绑定异常:'Newtonsoft.Json.Linq.JObject'不包含'Dump'的定义。
这对于LinqPad中几乎所有其他内容都起作用。我想找出一种方法,在输出属性名称、值等的同时,将Newtonsoft JObject对象Dump出来,就像其他对象一样。
我已经找到了如何将其转储为JSON字符串,但我希望看到输出一个对象而不仅仅是一个文本字符串。
对于任何想要从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进行快速操作时它会发挥作用。
这是一个静态扩展方法,因此您可以将其视为静态方法来调用:
LINQPad.Extensions.Dump(jObject);
我发现在某些情况下(我猜测)编译器无法绑定到扩展名,导致出现这种情况。
LinqPad的网站上有一篇文章和一篇博客文章介绍如何在dynamic
对象中使用Dump()
。
你可以尝试创建另一个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));
}
ExpandoObject
以及它实现的 IDictionary<string, object>
的特定内容,我认为。虽然 JObject
实现了 IDictionary<string, JToken>
,可能会产生良好的输出结果,但它并不是 通用 的动态对象处理方式。 - Jon SkeetDump()
,因为它的工作原理就是这样。 - D StanleyDump()
函数工作原理(我推测)是通过反射获取公共属性,并对集合、字典等进行特殊处理。 - D StanleyDump()
没有特殊处理来查看JObject
的弱类型Properties
集合以了解如何漂亮地打印它。 - D Stanleydynamic foo = ...;
foo.Dump();
扩展方法(Dump
就是其中之一)不适用于动态类型。如果您使用以下代码:
object foo = ...;
foo.Dump();
那么我希望它能够“正常”工作。但是,因为JObject
上的属性不是JSON属性,而是动态提供的,所以它可能并不会做你实际想要的事情。
(按照D Stanley的答案显式调用扩展方法也可以,但您可能会发现将其作为扩展方法仍然更方便。)
编辑:我强烈怀疑Dump
根本无法给您想要的内容,因为它对Json.NET一无所知,并且可能无法处理动态对象,就像调试器一样。您最好编写自己的Dump
方法来迭代JObject
的属性并递归地转储它们。如果您仍然希望找到开箱即用的内容,则应查看Json.NET文档而不是寻找LINQPad,尽管我不知道您是否会找到任何内容。
LINQPad的最新版本会自动对JSON.NET对象(如JObject
)进行漂亮的格式化,类似于被接受的答案中的ExpandoObject
。
有一个专门为此而编写的可视化工具。
添加 NMyVision.LinqPad.JsonVisualizer
NuGet包并调用JsonVisualizer.DumpJson(jObject)
,将会出现一个带有漂亮树形结构的选项卡。
在扩展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。
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();
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();
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
的引用,就像你为主查询所做的那样。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
扩展。
jo.ToObject<ExpandoObject>()
来代替序列化/反序列化。 - Jeff Mercado