Как сериализовать анонимный тип C # в строку JSON?

162

Я пытаюсь использовать следующий код для сериализации анонимного типа в JSON:

var serializer = new DataContractJsonSerializer(thing.GetType());
var ms = new MemoryStream();
serializer.WriteObject(ms, thing);
var json = Encoding.Default.GetString(ms.ToArray()); 

Тем не менее, я получаю следующее исключение, когда это выполняется:

Тип '<> f__AnonymousType1`3 [System.Int32, System.Int32, System.Object []]' не может быть сериализован. Попробуйте пометить его атрибутом DataContractAttribute, а все его элементы, которые вы хотите сериализовать, помечайте атрибутом DataMemberAttribute. См. Документацию Microsoft .NET Framework для других поддерживаемых типов.

Я не могу применить атрибуты к анонимному типу (насколько я знаю). Есть ли другой способ сделать эту сериализацию или я что-то упустил?

JC Grubbs
источник

Ответы:

159

Попробуйте JavaScriptSerializer вместо DataContractJsonSerializer

JavaScriptSerializer serializer = new JavaScriptSerializer();
var output = serializer.Serialize(your_anon_object);
Ник Берарди
источник
17
Похоже, что это было отменено в SP1.
Бисванат
7
для чего-то столь абсурдного, кажется, он используется во многих новых платформах Microsoft, включая MVC. aspnet.codeplex.com/SourceControl/changeset/view/21528#266491
Ник Берарди,
1
Как мне включить этот проект ia non-asp.net (консольное приложение)?
Alxandr
4
@Alxandr: Вам нужно будет ссылаться System.Web.Extensions.dllи добавить using System.Web.Script.Serialization;заявление.
randomguy
1
Проблема @randomgui была в том, что в качестве типа вывода проекта был задан профиль клиента.
Alxandr
75

Как уже упоминалось, Newtonsoft JSON.NET - хороший вариант. Вот конкретный пример простой сериализации JSON:

return JsonConvert.SerializeObject(
    new
    {
       DataElement1,
       SomethingElse
    });

Я обнаружил, что это очень гибкая, универсальная библиотека.

Мэтью Николс
источник
14

Вы можете попробовать мой ServiceStack JsonSerializer, это самый быстрый сериализатор .NET JSON на данный момент. Он поддерживает сериализацию DataContract, любого типа POCO, интерфейсов, объектов с поздним связыванием, включая анонимные типы и т. Д.

Основной пример

var customer = new Customer { Name="Joe Bloggs", Age=31 };
var json = customer.ToJson();
var fromJson = json.FromJson<Customer>(); 

Примечание: используйте Microsoftsofts JavaScriptSerializer только в том случае, если производительность не важна для вас, так как мне пришлось исключить ее из своих тестов, поскольку она в 40–100 раз медленнее, чем другие сериализаторы JSON.

mythz
источник
7
Я использую MS JavaScriptSerializer в стеке MVC3 для сериализации объектов с небольшими объемами данных. В этих случаях это довольно быстро, занимает менее миллисекунды, чтобы сделать то, что мне нужно. Сам запрос к БД занимает в 50-100 раз больше времени, поэтому в моей ситуации это не является существенным узким местом.
Брайан
2
Преждевременная оптимизация это ... ну вы знаете.
Матиас Ликкегор Лоренцен
1
Ссылка "самый быстрый сериализатор .NET JSON" - 404ing! Плюс этому ответу больше 5 с половиной лет. Есть ли у вас обновленная информация о производительности различных сериализаторов .NET JSON?
ErikE
11

Обратите внимание, что это с 2008 года. Сегодня я бы сказал, что сериализатор должен быть встроен и что вы, вероятно, можете использовать атрибуты swagger +, чтобы информировать потребителей о вашей конечной точке и возвращать данные.


Я бы сказал, что вы не должны сериализовать анонимный тип . Я знаю искушение здесь; Вы хотите быстро сгенерировать несколько одноразовых типов, которые просто будут использоваться в среде со свободными типами, которая называется Javascript в браузере. Тем не менее, я бы создал реальный тип и украсил бы его как Serializable. Тогда вы можете строго ввести свои веб-методы. Хотя это не имеет значения ни на йоту для Javascript, оно добавляет некоторую самодокументированность к методу. Любой опытный программист сможет взглянуть на сигнатуру функции и сказать: «О, это тип Foo! Я знаю, как это должно выглядеть в JSON».

Сказав это, вы можете попробовать JSON.Net для сериализации. Я понятия не имею, будет ли это работать

Джейсон Джексон
источник
3
JSON.Net работает просто отлично. Я бы сказал, что вы не должны :), я думаю, что это вполне законно во многих случаях.
апрель
2
После просмотра «выброшенных» типов, используемых в MVC, я вижу некоторые убедительные применения. Я думаю, что это очень удобный инструмент, чтобы иметь в своем наборе инструментов .Net.
Мэтью Уайтед
12
Этот момент я тоже смягчил, особенно в случае типов потребления. Но если объект совершает обратную поездку на сервер или используется более чем в одном месте, я все еще считаю, что создание типа приведет к меньшему количеству проблем.
Джейсон Джексон
Десериализация в стиле DataContract плохо обрабатывает полиморфные типы. Вы должны написать свой собственный десериализатор. Слишком много обслуживания кода.
micahhoover
Вариант использования, где сериализация анонимных типов полезна, это модульные тесты для веб-API.
Howcheng
9

Самый быстрый способ, который я нашел, был таким:

var obj = new {Id = thing.Id, Name = thing.Name, Age = 30};
JavaScriptSerializer serializer = new JavaScriptSerializer();
string json = serializer.Serialize(obj);

Пространство имен: System.Web.Script.Serialization.JavaScriptSerializer

i31nGo
источник
2
И для десериализации. , dynamic myObject = JsonConvert.DeserializeObject <dynamic> (вывод); , , ссылка: Newtonsoft.json.dll
i31nGo
2

Вы можете использовать Newtonsoft.Json.

var warningJSON = JsonConvert.SerializeObject(new {
                warningMessage = "You have been warned..."
            });
Ахмет Арслан
источник
1

Предполагая, что вы используете это для веб-службы, вы можете просто применить следующий атрибут к классу:

[System.Web.Script.Services.ScriptService]

Затем следующий атрибут для каждого метода, который должен возвращать Json:

[ScriptMethod(ResponseFormat = ResponseFormat.Json)]

И установите тип возвращаемого значения для методов, чтобы быть "объектом"

Павел
источник
Для стандартного веб-сервиса ASP [ScriptMethod (ResponseFormat = ResponseFormat.Json)] метод не требуется, [WebMethod] подойдет. Также вы не должны устанавливать тип возвращаемого значения для объекта, он может и должен быть строго типизирован с не сложным (то есть может быть сериализованным) типом.
row1
-1
public static class JsonSerializer
{
    public static string Serialize<T>(this T data)
    {
        try
        {
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
            var stream = new MemoryStream();
            serializer.WriteObject(stream, data);
            string jsonData = Encoding.UTF8.GetString(stream.ToArray(), 0, (int)stream.Length);
            stream.Close();
            return jsonData;
        }
        catch
        {
            return "";
        }
    }
    public static T Deserialize<T>(this string jsonData)
    {
        try
        {
            DataContractJsonSerializer slzr = new DataContractJsonSerializer(typeof(T));
            var stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonData));
            T data = (T)slzr.ReadObject(stream);
            stream.Close();
            return data;
        }
        catch
        {
            return default(T);
        }
    }
}
harryovers
источник
Это не сериализует анонимные типы в соответствии с вопросом
Марк Соул