Как я могу сбросить() объект Newtonsoft JObject в LinqPad?

В LinqPad попытка вызова .Dump() в Newtonsoft JSON.Net JObject дает исключение:

RuntimeBinderException: "Newtonsoft.Json.Linq.JObject" не содержит определения для "Дамп".

Это работает почти во всем остальном в LinqPad. Я хотел бы выяснить метод, который выведет Newtonsoft JObject, как и другие объекты, показывая имена свойств, значения и т.д.

Я уже понял, как заставить его сбрасывать строку JSON, но я хотел бы, чтобы объект получал вывод, а не только текстовую строку.

Ответы

Ответ 1

Для тех, кто приземляется здесь, желая получить прекрасный вывод LINQPad из строки JSON, десериализация до 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 Dump() method.
    }
}

Не самый эффективный метод, но для быстрого использования при копании в LINQPad он сделает трюк.

Ответ 2

Это статический метод расширения, поэтому вы можете вызывать его как статический метод:

LINQPad.Extensions.Dump(jObject);

Я вижу, что это происходит на некоторых типах, когда (я предполагаю) компилятор не может связываться с расширением по какой-то причине.

Там пост на сайте LINQPad и сообщение в блоге относительно использования Dump() с dynamic объектами.

Вы можете попробовать создать другое расширение Dump(), которое проверяет свойства JObject и создать словарь, который может быть JObject Dump.

Примерно так: (полная 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));
}

Ответ 3

Я предполагаю, что вы делаете что-то вроде этого:

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

Методы расширения (которые Dump) не работают с динамической типизацией. Если вы используете:

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

тогда я ожидаю, что он "сработает" хорошо. Он может не делать то, что вам действительно нужно, потому что свойства на JObject не являются свойствами JSON, которые предоставляются динамически.

(Вызов метода расширения в явном виде в соответствии с ответом D Stanley тоже будет работать, но вы можете счесть его более удобным для использования в качестве метода расширения.)

EDIT: я сильно подозреваю, что Dump просто не даст вам то, что вы хотите, учитывая, что он ничего не знает о Json.NET и, вероятно, не обрабатывает динамические объекты так, как это (например) отладчик. Вероятно, вам лучше всего написать собственный метод Dump, чтобы перебирать свойства JObject и рекурсивно выгружать их. Если вы все еще надеетесь найти что-то из коробки, вероятно, вам стоит посмотреть в документации Json.NET, а не искать LINQPad, хотя я не знаю найдете ли вы что-нибудь.

Ответ 4

JObject действительно не имеет свойств, это куча JArray и JProperty gunk. Вы можете использовать метод расширения напрямую, как это было предложено предыдущим ответом, или отбросить динамику до 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.

Ответ 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, я придумал следующее:

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

Используя LINQPad new 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 так же, как и для основного запроса

Ответ 8

Там визуализатор написан специально для этой цели.

Включите NMyVision.LinqPad.JsonVisualizer NuGet NMyVision.LinqPad.JsonVisualizer и вызовите JsonVisualizer.DumpJson(jObject), и появится вкладка с симпатичным небольшим древовидным представлением.

JsonVisualizer Output

Ответ 9

Я только что пробовал это сегодня с JObject, добавив библиотеку JSON.NET через Nuget, и я получаю структурированные данные назад (и без ошибок) из data.Dump(), где данные являются JObject.

enter image description here