如何在LinqPad中转储()一个Newtonsoft JObject?
在LinqPad中,尝试在Newtonsoft JSON.Net JObject
上调用.Dump()
JObject
产生exception:
RuntimeBinderException:’Newtonsoft.Json.Linq.JObject’不包含’转储’的定义。
这适用于LinqPad中的几乎所有其他内容。 我想找出一个方法,它将转储一个Newtonsoft JObject
,就像其他对象一样,显示属性名称,值等。
我已经想出如何让它转储JSON字符串,但我希望看到一个对象得到输出而不仅仅是一个文本字符串。
对于那些希望从JSON字符串获得漂亮的LINQPad输出的人来说,反序列化为ExpandoObject
是一种有效的方法,并且可以递归地在数据中的任何层次结构中运行:
JsonConvert.DeserializeObject
扩展它以涵盖实际问题,JObject上的这些行的扩展方法可以解决这个问题:
public static class ExtMethods { public static JObject DumpPretty(this JObject jo) { var jsonString = JsonConvert.SerializeObject(jo); JsonConvert.DeserializeObject(jsonString).Dump(); return jo; // return input in the spirit of LINQPad's Dump() method. } }
不是最有效的方法,但是为了在LINQPad中挖掘时快速使用它可以解决问题。
它是一个静态扩展方法,因此您可以将其称为静态方法:
LINQPad.Extensions.Dump(jObject);
我看到在某些类型上发生这种情况(我认为)编译器由于某种原因无法绑定到扩展名。
在LinqPad的网站上有一篇文章和一篇关于将Dump()
与dynamic
对象一起使用的博文 。
您可以尝试创建另一个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)); }
我的猜测是你正在做这样的事情:
dynamic foo = ...; foo.Dump();
扩展方法( Dump
是)不适用于动态类型。 如果您使用:
object foo = ...; foo.Dump();
然后我预计它会“正常”工作。 它可能不会做你真正想要的 – 因为JObject
上的属性不是动态提供的JSON属性。
(根据D Stanley的回答明确地调用扩展方法也会起作用,但是你可能会发现它仍然作为扩展方法更方便。)
编辑:我强烈怀疑Dump
根本不会给你你想要的东西,因为它对Json.NET一无所知,并且可能不会像(比如说)调试器那样处理动态对象。 您可能最好编写自己的Dump
方法来迭代JObject
的属性并以递归方式转储它们。 如果你仍然希望找到开箱即用的东西,你可能应该查看Json.NET文档,而不是寻找LINQPad,虽然我不知道你是否会发现任何东西。
JObject
没有真正的属性,它是一堆JArray
和JProperty
。 您可以按照上一个答案的建议直接使用扩展方法,也可以将动态转换为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
方法 ,它在转储时将普通对象转换为 json。 我提到它主要是因为它描述了如何编写自定义Dump
扩展。
这似乎很好地解决了这个问题:
dynamic dyn = ... // parse some JSON or whatever ((JObject)dyn).Properties().ToDictionary(p=>p.Name, p=>p.Value).Dump();
如果你有一个列表,这有效:
dynamic[] dyns = ... dyns.Cast().Select(o => o.Properties().ToDictionary(p => p.Name, p => p.Value)).Dump();
此外,如果你有一个linqpad程序,这很方便:
static class JsonNetDumper { public static IEnumerable> ToDumpable(this IEnumerable
您可以这样使用:
dynamic[] dyns = ... dyns.ToDumpable().Dump();
扩展rdavisau的想法 ,我想出了这个:
public static class ExtMethods { public static object Dumpable(this JToken t) { if(t is JObject) { var json = JsonConvert.SerializeObject(t); return JsonConvert.DeserializeObject(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的数组和查询结果。
使用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(); return input; }
您还需要添加对Netwonsoft.Json
的引用,与您对主查询的引用相同
我今天刚刚尝试使用JObject,通过Nuget添加了JSON.NET库,我从data.Dump()获取结构化数据(并且没有错误),其中数据是JObject。
- 如何在c#中找到名称以某个字符串开头的HTML元素的数量?
- ConfigurationElementCollection具有许多不同类型的ConfigurationElements
- 范围无法删除。 在Microsoft.Office.Interop.Word.Range.set_Text(String prop)
- dependency injection统一 – 条件解析
- 将web.config部分读取到List
- Workflow Foundation 4中的dependency injection/ IoC
- 使用C#在Excel / VSTO中的列号为列号
- 设置C#可选参数的默认值
- 如何将两种类型的C#列表合并为一个?