简体   繁体   English

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

[英]How do I serialize a C# anonymous type to a JSON string?

I'm attempting to use the following code to serialize an anonymous type to JSON:我正在尝试使用以下代码将匿名类型序列化为 JSON:

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

However, I get the following exception when this is executed:但是,执行此操作时出现以下异常:

Type '<>f__AnonymousType1`3[System.Int32,System.Int32,System.Object[]]' cannot be serialized.类型 '<>f__AnonymousType1`3[System.Int32,System.Int32,System.Object[]]' 无法序列化。 Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute.考虑使用 DataContractAttribute 特性标记它,并使用 DataMemberAttribute 特性标记要序列化的所有成员。 See the Microsoft .NET Framework documentation for other supported types.有关其他支持的类型,请参阅 Microsoft .NET Framework 文档。

I can't apply attributes to an anonymous type (as far as I know).我不能将属性应用于匿名类型(据我所知)。 Is there another way to do this serialization or am I missing something?有没有另一种方法可以进行这种序列化,还是我遗漏了什么?

Try the JavaScriptSerializer instead of the DataContractJsonSerializer尝试使用 JavaScriptSerializer 而不是 DataContractJsonSerializer

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

As others have mentioned, Newtonsoft JSON.NET is a good option.正如其他人提到的, Newtonsoft JSON.NET是一个不错的选择。 Here is a specific example for simple JSON serialization:以下是简单 JSON 序列化的具体示例:

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

I have found it to be a very flexible, versatile library.我发现它是一个非常灵活、多功能的库。

You can try my ServiceStack JsonSerializer it's the fastest .NET JSON serializer at the moment.你可以试试我的 ServiceStack JsonSerializer,它是目前最快的 .NET JSON 序列化器 It supports serializing DataContract's, Any POCO Type, Interfaces, Late-bound objects including anonymous types, etc.它支持序列化 DataContract、任何 POCO 类型、接口、后期绑定对象(包括匿名类型)等。

Basic Example基本示例

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

Note: Only use Microsofts JavaScriptSerializer if performance is not important to you as I've had to leave it out of my benchmarks since its up to 40x-100x slower than the other JSON serializers.注意:只有在性能对您不重要的情况下才使用 Microsoft 的 JavaScriptSerializer,因为我不得不将它排除在我的基准测试之外,因为它比其他 JSON 序列化器慢40 到 100 倍

The fastest way I found was this:我找到的最快的方法是这样的:

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

Namespace: System.Web.Script.Serialization.JavaScriptSerializer命名空间:System.Web.Script.Serialization.JavaScriptSerializer

Please note this is from 2008. Today I would argue that the serializer should be built in and that you can probably use swagger + attributes to inform consumers about your endpoint and return data.请注意这是从 2008 年开始的。今天我认为应该内置序列化程序,并且您可能可以使用 swagger + 属性来通知消费者您的端点并返回数据。


Iwould argue that you shouldn't be serializing an anonymous type .我会争辩说你不应该序列化一个匿名类型 I know the temptation here;我知道这里的诱惑; you want to quickly generate some throw-away types that are just going to be used in a loosely type environment aka Javascript in the browser.您想快速生成一些将在松散类型环境(即浏览器中的 Javascript)中使用的一次性类型。 Still, I would create an actual type and decorate it as Serializable.尽管如此,我还是会创建一个实际类型并将其装饰为可序列化。 Then you can strongly type your web methods.然后你可以强类型你的网络方法。 While this doesn't matter one iota for Javascript, it does add some self-documentation to the method.虽然这对 Javascript 来说并不重要,但它确实为该方法添加了一些自我文档。 Any reasonably experienced programmer will be able to look at the function signature and say, "Oh, this is type Foo! I know how that should look in JSON."任何有一定经验的程序员都能够查看函数签名并说:“哦,这是 Foo 类型!我知道它在 JSON 中应该是什么样子。”

Having said that, you might try JSON.Net to do the serialization.话虽如此,您可以尝试使用JSON.Net进行序列化。 I have no idea if it will work我不知道它是否会起作用

For those checking this around the year 2020:对于那些在 2020 年左右进行检查的人:

Microsoft's System.Text.Json namespace is the new king in town.微软的 System.Text.Json 命名空间是新的王者。 In terms of performance, it is the best as far as I can tell:在性能方面,据我所知,它是最好的:

var model = new Model
{
    Name = "Test Name",
    Age = 5
};

string json = JsonSerializer.Serialize(model);

As some others have mentioned, NewtonSoft.Json is a very nice library as well.正如其他人所提到的,NewtonSoft.Json 也是一个非常好的库。

You could use Newtonsoft.Json.您可以使用 Newtonsoft.Json。

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

A faster alternative with Microsofts' new library on System.Text.Json微软在 System.Text.Json 上的新库的更快替代方案

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

Assuming you are using this for a web service, you can just apply the following attribute to the class:假设您将其用于 Web 服务,您只需将以下属性应用于该类:

[System.Web.Script.Services.ScriptService]

Then the following attribute to each method that should return Json:然后为每个应该返回 Json 的方法添加以下属性:

[ScriptMethod(ResponseFormat = ResponseFormat.Json)]

And set the return type for the methods to be "object"并将方法的返回类型设置为“对象”

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM