Як я серіалізую анонімний тип 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.

Я не можу застосувати атрибути до анонімного типу (наскільки я знаю). Чи є інший спосіб зробити цю серіалізацію чи я щось пропускаю?

Відповіді:


159

Спробуйте JavaScriptSerializer замість DataContractJsonSerializer

JavaScriptSerializer serializer = new JavaScriptSerializer();
var output = serializer.Serialize(your_anon_object);

17
Зворотний зв'язок, схоже, у SP1 він був застарілий.
Biswanath

7
Щось таке настільне, воно, як видається, звикає до багатьох нових рамок Microsoft, включаючи MVC. aspnet.codeplex.com/SourceControl/changeset/view/21528#266491
Нік Берарді

1
Як включити цей проект ia non-asp.net (консольний додаток)?
Алксандр

4
@Alxandr: Вам потрібно буде посилатися System.Web.Extensions.dllта додати using System.Web.Script.Serialization;заяву.
randomguy

1
Проблема @randomgui полягала в тому, що тип виходу проекту було встановлено на профіль клієнта.
Олександр

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>(); 

Примітка: Використовуйте Microsofts JavaScriptSerializer лише тоді, коли продуктивність для вас не важлива, оскільки мені довелося залишати її поза моїми орієнтирами, оскільки її до 40x-100x повільніше, ніж інші серіалізатори JSON.


7
Я використовую MS JavaScriptSerializer на стеку MVC3, щоб серіалізувати об'єкти з невеликою кількістю даних. У цих випадках досить швидко, зайнявши менше мілісекунди, щоб зробити те, що мені потрібно. Сам запит на DB займає 50x-100x довше, тому це насправді не є істотним вузьким місцем у моїй ситуації.
Брайан

2
Передчасна оптимізація - це добре, ви знаєте.
Mathias Lykkegaard Lorenzen

1
"найшвидший серіалізатор .NET JSON" - це 404ing! Плюс ця відповідь старше 5 1/2 років. У вас є оновлення продуктивності різних серіалізаторів .NET JSON?
ErikE

11

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


Я б заперечив, що ви не повинні серіалізувати анонімний тип . Я знаю тут спокусу; ви хочете швидко генерувати деякі типи викидання, які просто використовуватимуться у середовищі з дуже слабким типом aka Javascript у браузері. Все-таки я створив би фактичний тип і прикрасив би його як серіалізаційний. Тоді ви можете сильно ввести свої веб-методи. Хоча для Javascript це не має значення жодної йоти, він додає метод самостійної документації. Будь-який досить досвідчений програміст зможе подивитися на підпис функції та сказати: "О, це тип Foo! Я знаю, як це має виглядати в JSON".

Сказавши це, ви можете спробувати JSON.Net зробити серіалізацію. Я не маю уявлення, чи спрацює це


3
JSON.Net працює чудово. Я б заперечував, що не варто :), я думаю, що це в багатьох випадках досить законно.
квітня

2
Після побачення типів "викинути", що використовуються в MVC, я можу побачити деякі переконливі способи використання. Я думаю, що це дуже зручний інструмент, який можна мати у вашому інструменті .Net.
Метью Віт

12
Це питання, на якому я також пом'якшився, особливо у випадках споживання лише для споживання. Але якщо об’єкт здійснює зворотну поїздку на сервер або використовується в більш ніж одному місці, я все одно вважаю, що створення типу призведе до менших проблем.
Джейсон Джексон

Десерталізація стилю DataContract не справляється з поліморфними типами. Ви повинні написати власний де-серіалізатор. Занадто багато обслуговування коду.
Міхеховер

Випадком використання, коли корисна серіалізація анонімних типів, є одиничні тести для веб-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


2
А для десеріалізації:. . динамічний myObject = JsonConvert.DeserializeObject <динамічний> (вихід); . . довідка: 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] зробить це. Крім того, ви не повинні встановлювати тип повернення для об'єкта, він може бути і повинен бути сильно набраний нескладним (тобто може бути серіалізованим) типом.
рядок1

-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);
        }
    }
}

Це не серіалізує анонімні типи відповідно до запитання
Марк Совул
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.