如何将C#匿名类型序列化为JSON字符串?


161

我正在尝试使用以下代码将匿名类型序列化为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文档。

据我所知,我不能将属性应用于匿名类型。是否有另一种方法来执行此序列化,或者我缺少什么?

Answers:


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项目(控制台应用程序)?
Alxandr

4
@Alxandr:您需要引用System.Web.Extensions.dll并添加一条using System.Web.Script.Serialization;语句。
randomguy

1
@randomgui问题是项目输出类型设置为客户端配置文件。
Alxandr


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

注意:如果性能对您不重要,请仅使用Microsoft的JavaScriptSerializer,因为我不得不将其排除在基准测试之外,因为它的速度比其他JSON序列化器慢40到100倍


7
我在MVC3堆栈上使用MS JavaScriptSerializer来序列化带有少量数据的对象。在这些情况下,速度非常快,只需不到一毫秒即可完成我需要的操作。数据库查询本身要花费50到100倍的时间,因此在我的情况下,这并不是一个明显的瓶颈。
布莱恩(Brian)

2
过早的优化是...您知道。
Mathias Lykkegaard Lorenzen 2014年

1
“最快的.NET JSON序列化程序”链接是404ing!另外,这个答案已经超过5 1/2年了。您是否对各种.NET JSON序列化器的性能进行了更新?
ErikE '16

11

请注意,这是从2008年开始的。今天,我认为应该内置串行器,并且您可以使用swagger +属性来通知使用者有关您的端点并返回数据。


我认为你不应该序列化一个匿名类型。我知道这里的诱惑;您想要快速生成一些一次性类型,这些类型将在浏览器中的松散类型环境(也称为Javascript)中使用。尽管如此,我还是会创建一个实际的类型并将其装饰为Serializable。然后,您可以强烈键入您的Web方法。尽管这对于Javascript来说无关紧要,但确实为该方法添加了一些自文档。任何经验丰富的程序员都可以看一下函数签名,然后说:“哦,这是Foo类型!我知道在JSON中应该如何看。”

话虽如此,您可以尝试使用JSON.Net进行序列化。我不知道是否行得通


3
JSON.Net可以正常工作。我认为您不应该:),在许多情况下,我认为这是相当合法的。
2008年

2
看到MVC中使用的“丢弃”类型后,我可以看到一些引人注目的用法。我认为这是您的.Net工具箱中非常方便的工具。
Matthew Whited

12
我也强调了这一点,特别是在仅消耗类型的情况下。但是,如果对象正在返回服务器,或者在多个位置使用了该对象,我仍然相信创建类型将导致较少的问题。
杰森·杰克逊

DataContract样式反序列化不能很好地处理多态类型。您必须编写自己的反序列化器。代码维护过多。
micahhoover 2015年

序列化匿名类型很有用的一个用例是Web API的单元测试。
howcheng 2016年

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 <dynamic>(输出); 。。参考:Newtonsoft.json.dll
i31nGo 2014年

2

您可以使用Newtonsoft.Json。

var warningJSON = JsonConvert.SerializeObject(new {
                warningMessage = "You have been warned..."
            });

1

假设您将其用于Web服务,则可以将以下属性应用于该类:

[System.Web.Script.Services.ScriptService]

然后,为每个应返回Json的方法提供以下属性:

[ScriptMethod(ResponseFormat = ResponseFormat.Json)]

并将方法的返回类型设置为“对象”


对于该方法不需要标准的ASP Web服务[ScriptMethod(ResponseFormat = ResponseFormat.Json)],[WebMethod]将需要。同样,您不应该将返回类型设置为object,可以并且应该使用非复杂(即可以序列化)类型来强类型化返回类型。
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);
        }
    }
}

这不会按照问题序列化匿名类型
Mark Sowul
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.