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


Я пытаюсь использовать следующий код для сериализации анонимного типа в 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. Видеть Майкрософт .Чистая Рамки документация для других поддерживаемых типы.

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

7 151

7 ответов:

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

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

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

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

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

вы можете попробовать мой 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.

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

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

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

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

Пространство Имен: Системы.Сеть.Скрипт.Сериализация.JavaScriptSerializer

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

[System.Web.Script.Services.ScriptService]

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

[ScriptMethod(ResponseFormat = ResponseFormat.Json)]

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

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