【问题标题】:How can I Dump() a Newtonsoft JObject in LinqPad?如何在 LinqPad 中转储() Newtonsoft JObject?
【发布时间】:2013-01-18 20:03:40
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: c# json linqpad json.net


    【解决方案1】:

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

    【讨论】:

    • 很好的解决方案!到目前为止,这与 linqpads 转储出所有答案的效果最好。
    • 其他 JSON 类型的扩展见stackoverflow.com/a/35042280/859211
    • p.s.,您可以只使用 jo.ToObject&lt;ExpandoObject&gt;() 而不是序列化/反序列化。
    • 使用函数名 Dump 代替 DumpPretty 怎么样。我可以使用 jo.Dump() !!
    【解决方案2】:

    它是一个静态扩展方法,所以你可以把它当成静态方法来调用:

    LINQPad.Extensions.Dump(jObject);
    

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

    在 LinqPad 上有 a post 的网站和 a blog post 关于使用 Dump()dynamic 对象。

    您可以尝试创建另一个 Dump() 扩展来检查JObject 的属性,并创建一个可以漂亮地成为Dumped 的字典。

    类似这样的:(完整的 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));
    }
    

    【讨论】:

    • 不幸的是,这并不能真正解决问题。这会吐出一组嵌套的值,但不显示属性名称,因此您无法对其进行正面或反面。
    • 我相信这篇博文是针对ExpandoObject 以及它实现IDictionary&lt;string, object&gt; 的方式。 可能JObject 实现IDictionary&lt;string, JToken&gt; 会提供不错的输出,但它不是一般动态对象处理。
    • @KenMason 那么你不能使用 LinqPad 的 Dump(),因为它是这样工作的。
    • 不...这不是 Newtonsoft 的 JObject 的工作方式。这就是这篇文章的重点。 :)
    • 我的意思是,LinqPad 的Dump() 工作(我认为)通过使用反射来获取公共属性,对集合、字典等进行一些特殊处理。
    【解决方案3】:

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

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

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

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

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

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

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

    【讨论】:

    • 不幸的是,这并不能真正解决问题。这会吐出一组嵌套的值,但不显示属性名称,因此您无法对其进行正面或反面。
    • @KenMason:这就是调用 LINQPad Dump 方法。这就是我的回答,说它可能不会做你想要的......它使用对象的 actual 属性,而不是动态属性。我怀疑您可能找不到任何完全按照您的意愿进行操作的方法-至少不是开箱即用的。我和 D Stanley 的答案都是合理的(IMO),就您如何使用Dump 的实际问题而言......只是Dump 没有做你想做的事。
    【解决方案4】:

    更新

    最新版本的 LINQPad 可以很好地自动格式化 JSON.NET 对象,例如 JObject(类似于已接受答案中的 ExpandoObject)。

    原始答案

    a visualizer专门为此目的写的。

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

    【讨论】:

      【解决方案5】:

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

      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】:

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

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

        【讨论】:

          【解决方案7】:

          JObject 并没有真正的属性,它是一堆JArrayJProperty 的垃圾。您可以按照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 扩展。

          【讨论】:

            【解决方案8】:

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

            将此 sn-p 添加到 LINQPad 的 My Extensions 查询

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

            您还需要添加对Netwonsoft.Json 的引用,就像您对主查询所做的一样

            【讨论】:

              【解决方案9】:

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

              【讨论】:

              • 这种方法的问题是您看不到键,只能看到值。
              • 正确 - 符合我的目的,但不是解决方案
              猜你喜欢
              • 1970-01-01
              • 2021-02-22
              • 1970-01-01
              • 2015-10-14
              • 2017-09-08
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-01-20
              相关资源
              最近更新 更多