Как сериализовать ExpandoObject с помощью ServiceStack JsonSerializer?


Можно ли заставить ServiceStack JsonSerializer сериализовать ExpandoObject как плоский объект, а не словарь? Что-то примерно приближенное к этому:

{"x":"xvalue","y":"/Date(1313966045485)/"}

Я пытаюсь сравнить сериализацию JSON ExpandoObject с использованием трех различных систем: .NET BCL JavaScriptSerializer, Newtonsoft JSON.NET, и предложение Servicestack's JSON.

Я начинаю с довольно простого динамического объекта.
dynamic test = new ExpandoObject();
test.x = "xvalue";
test.y = DateTime.Now;

Кажется, что сериализатору проще обрабатывать ExpandoObject как IDictionary<string, object>. И BCL, и ServiceStack начинают с этого пути, хотя и идут довольно разными маршрутами с результатом.

JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
Console.WriteLine(javaScriptSerializer.Serialize(test));
// [{"Key":"x","Value":"xvalue"},{"Key":"y","Value":"/Date(1313966045485)/"}]

Console.WriteLine(ServiceStack.Text.JsonSerializer.SerializeToString(test));
// ["[x, xvalue]","[y, 8/21/2011 16:59:34 PM]"]

Я бы предпочел, чтобы ExpandoObject сериализовался больше, поскольку он собран в коде, как типичный класс будет сериализован. Вы можете добавить переопределяющий сериализатор JavaScript в систему BCL для IDictionary<string, object>. Это отлично работает, предполагая, что на самом деле у вас нет IDictionary<string, object>, который должен оставаться таким (чего я пока не делаю).

JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
javaScriptSerializer.RegisterConverters(new JavaScriptConverter[] { new ExpandoJsonConverter() });
Console.WriteLine(javaScriptSerializer.Serialize(test));
// {"x":"xvalue","y":"/Date(1313966045485)/"}

К сожалению, Я по-прежнему нужен способ, чтобы получить JsonSerializer ServiceStack для лечения ExpandoObject в том же стиле. Как мне подключиться к системе ServiceStack, чтобы сделать это возможным?

Update: хотя это не вариант для моего использования, похоже, что ServiceStack отлично обрабатывает анонимные объекты.

Console.WriteLine(ServiceStack.Text.JsonSerializer.SerializeToString(new { x = "xvalue", y = DateTime.Now }));
// {"x":"xvalue","y":"/Date(1313980029620+0000)/"}
1 6

1 ответ:

В Jsonserializer ServiceStack нет никаких крючков, которые вы можете подключить, чтобы изменить это поведение, но я буду более чем счастлив принять запрос на вытягивание, который это делает;)

Классы, которые вам нужно будет изменить:

  • JsWriter.cs (строка 223) - вставка кода для обнаружения объекта expando и возврата делегата, который записывает объект expando так, как вы хотите.
  • JsReader (строка 42) - вставить код для обнаружения объекта expando и возврата делегат для чтения содержимого строки и десериализации его обратно в expando

Я полагаю, что код для работы с объектом expando похож на словарь, поэтому вы должны иметь возможность использовать классы реализации словаря, чтобы направлять вас (т. е. WriteDictionary.cs и DeserializeDictionary.cs )

Не стесняйтесь использовать форум ServiceStack, если у вас есть еще какие-либо вопросы / проблемы по этому поводу: https://groups.google.com/forum/#! forum / servicestack