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

Posted

技术标签:

【中文标题】如何将 C# 匿名类型序列化为 JSON 字符串?【英文标题】:How do I serialize a C# anonymous type to a JSON string? 【发布时间】:2010-09-24 19:44:45 【问题描述】:

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

我无法将属性应用于匿名类型(据我所知)。还有其他方法可以进行此序列化还是我遗漏了什么?

【问题讨论】:

【参考方案1】:

试试 javascriptSerializer 而不是 DataContractJsonSerializer

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

【讨论】:

Trackback,它似乎在 SP1 中已被弃用。 对于如此过时的东西,它似乎被用于许多新的 Microsoft 框架,包括 MVC。 aspnet.codeplex.com/SourceControl/changeset/view/21528#266491 如何在非 asp.net 项目(控制台应用程序)中包含这个? @Alxandr:您需要引用System.Web.Extensions.dll 并添加using System.Web.Script.Serialization; 语句。 @randomgui 问题是项目输出类型设置为客户端配置文件。【参考方案2】:

正如其他人所提到的,Newtonsoft JSON.NET 是一个不错的选择。下面是一个简单的 JSON 序列化的具体例子:

return JsonConvert.SerializeObject(
    new
    
       DataElement1,
       SomethingElse
    );

我发现它是一个非常灵活、多功能的库。

【讨论】:

【参考方案3】:

您可以试试我的 ServiceStack JsonSerializer,目前是 fastest .NET JSON serializer。它支持序列化 DataContract's、任何 POCO 类型、接口、包括匿名类型在内的后期绑定对象等。

基本示例

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

注意:仅当性能对您不重要时才使用 Microsoft 的 JavaScriptSerializer,因为我不得不将它排除在我的基准测试之外,因为它比其他 JSON 序列化程序慢 40x-100x

【讨论】:

我正在使用 MVC3 堆栈上的 MS JavaScriptSerializer 来序列化具有少量数据的对象。在这些情况下它非常快,只需不到一毫秒即可完成我需要的操作。数据库查询本身需要 50 倍到 100 倍的时间,所以在我的情况下,这并不是真正的重大瓶颈。 过早的优化是...你知道的。 “最快的 .NET JSON 序列化程序”链接是 404ing!另外,这个答案已经超过 5 1/2 年了。你有关于各种 .NET JSON 序列化程序性能的更新吗?【参考方案4】:

我发现最快的方法是这样的:

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

【讨论】:

对于反序列化:. .动态 myObject = JsonConvert.DeserializeObject(输出); . .参考:Newtonsoft.json.dll【参考方案5】:

请注意这是从 2008 年开始的。今天我认为应该内置序列化程序,并且您可能可以使用 swagger + 属性来告知消费者您的端点并返回数据。


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

话虽如此,您可以尝试 JSON.Net 进行序列化。我不知道它是否会起作用

【讨论】:

JSON.Net 工作得很好。我认为你不应该:),我认为在很多情况下它是非常合法的。 在看到 MVC 中使用的“丢弃”类型之后,我可以看到一些引人注目的用途。我认为这是您的 .Net 工具箱中非常方便的工具。 这一点我也软化了,尤其是在仅消费类型的情况下。但是如果对象是返回服务器,或者在多个位置使用,我仍然相信创建一个类型会导致更少的问题。 DataContract 风格的反序列化不能很好地处理多态类型。您必须编写自己的反序列化程序。代码维护过多。 序列化匿名类型很有用的一个用例是 Web API 的单元测试。【参考方案6】:

对于那些在 2020 年左右检查的人:

Microsoft 的 System.Text.Json 命名空间是镇上的新王。在性能方面,据我所知,它是最好的:

var model = new Model

    Name = "Test Name",
    Age = 5
;

string json = JsonSerializer.Serialize(model);

正如其他人所提到的,NewtonSoft.Json 也是一个非常好的库。

【讨论】:

【参考方案7】:

您可以使用 Newtonsoft.Json。

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

微软在 System.Text.Json 上的新库的更快替代

var warningJSON = JsonSerializer.Serialize(new 
               warningMessage = "You have been warned..."
            );

【讨论】:

【参考方案8】:

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

[System.Web.Script.Services.ScriptService]

然后为每个应该返回 Json 的方法添加以下属性:

[ScriptMethod(ResponseFormat = ResponseFormat.Json)]

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

【讨论】:

对于标准的 ASP Web 服务 [ScriptMethod(ResponseFormat = ResponseFormat.Json)] 方法不需要,[WebMethod] 可以。此外,您不应该将返回类型设置为对象,它可以并且应该使用非复杂(即可以序列化)类型进行强类型化。【参考方案9】:
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);
        
    

【讨论】:

这不会根据问题序列化匿名类型

以上是关于如何将 C# 匿名类型序列化为 JSON 字符串?的主要内容,如果未能解决你的问题,请参考以下文章

将 json 反序列化为匿名类型列表

在调用API后,将JSON对象反序列化为C#类[重复]。

如何将 JSON 反序列化为正确类型的对象,而无需事先定义类型?

C# - Web API - 将枚举序列化为带空格的字符串

将 JSON 字符串反序列化为多个 C# 对象

C# 是否可以将 动态或匿名类型 转成 强类型 ?