在.NET中,我如何将C#对象转换为JSON字符串?

1233

我有这样的类:

class MyDate
{
    int year, month, day;
}

class Lad
{
    string firstName;
    string lastName;
    MyDate dateOfBirth;
}

我想将一个Lad对象转换为像这样的JSON字符串:

{
    "firstName":"Markoff",
    "lastName":"Chaney",
    "dateOfBirth":
    {
        "year":"1901",
        "month":"4",
        "day":"30"
    }
}

(不带格式)。我找到了这个链接,但它使用的命名空间不在.NET 4中。我也听说过JSON.NET,但他们的网站目前似乎无法访问,而且我不想使用外部DLL文件。

除了手动创建JSON字符串编写器之外,还有其他选择吗?


4
JSON.net可以在这里下载(http://json.codeplex.com/)。另外一个更快的解决方案是ServiceStack.Text(据说更快,但我自己没有测试过)。(作者)不建议自己编写JSON解析器。它可能会更慢、更容易出错,或者需要投入大量时间。 - Zebi
1
是的,C#有一种叫做JavaScriptSerializer的类型。 - Glenn Ferrie
可能是Generics / JSON JavaScriptSerializer C#的重复问题。 - Filip Ekberg
3
根据我的观察,您应该能够使用http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx。根据MSDN页面,它也适用于.Net 4.0。您应该能够使用Serialize(Object obj)方法:http://msdn.microsoft.com/en-us/library/bb292287.aspx。我有遗漏什么吗?顺便说一下,您的链接似乎是一些代码而不是一个链接。 - Holger
更不用提它对System.Web.Xyz命名空间没有依赖... - Dave Jellison
15个回答

1441

既然我们都喜欢一句话简述

......这个要依赖Newtonsoft NuGet包,它比默认的序列化器更流行且更好。

Newtonsoft.Json.JsonConvert.SerializeObject(new {foo = "bar"})

文档:序列化和反序列化 JSON


167
Newtonsoft 序列化程序比内置的更快速且更可定制。强烈推荐使用它。感谢 @willsteel 的答案。 - Andrei
9
@JosefPfleger,这个价格是针对 JSON.NET Schema 而非普通的 JSON.NET 序列化程序的,JSON.NET 序列化程序采用 MIT 许可证。 - David Cumps
37
如果您阅读JavaScriptSerializer的MSDN文档,它明确表示应使用JSON.net。 - dsghi
6
@JosefPfleger,Newtionsoft JSON.net 是 MIT 许可证下的,如果您愿意,可以对其进行修改并转售。他们的定价页面是关于商业技术支持和一些模式验证器。 - cb88
5
对于所有阅读此内容的人,请注意这个答案非常旧了。尽管 Newtonsoft.Json 仍然非常流行并且可以胜任工作,但请考虑使用其他答案中提到的新的(内置的)System.Text.Json。 - Jim Aho
显示剩余4条评论

1019

请注意

微软建议您不要使用JavaScriptSerializer

请参考文档页面的头部:

对于 .NET Framework 4.7.2 及更高版本,请使用 System.Text.Json 命名空间中的 API 进行序列化和反序列化。对于早期版本的 .NET Framework,请使用 Newtonsoft.Json。


原始回答:

您可以使用 JavaScriptSerializer 类(添加对 System.Web.Extensions 的引用):

using System.Web.Script.Serialization;
var json = new JavaScriptSerializer().Serialize(obj);

一个完整的示例:

using System;
using System.Web.Script.Serialization;

public class MyDate
{
    public int year;
    public int month;
    public int day;
}

public class Lad
{
    public string firstName;
    public string lastName;
    public MyDate dateOfBirth;
}

class Program
{
    static void Main()
    {
        var obj = new Lad
        {
            firstName = "Markoff",
            lastName = "Chaney",
            dateOfBirth = new MyDate
            {
                year = 1901,
                month = 4,
                day = 30
            }
        };
        var json = new JavaScriptSerializer().Serialize(obj);
        Console.WriteLine(json);
    }
}

121
请注意,微软建议使用JSON.net代替此解决方案。我认为这个答案现在已经不合适了。请看一下willsteel的回答。来源:https://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx。 - rzelek
14
@DarinDimitrov,你应该考虑添加一个关于JSON.net的提示。微软推荐其使用而不是JavascriptSerializer:https://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx 你还可以添加一个提示到 https://msdn.microsoft.com/en-us/library/system.runtime.serialization.json.datacontractjsonserializer(v=vs.110).aspx,这是框架内置的方法。 - Mafii
2
这里有一个在线工具,可以将你的类转换为json格式。希望能帮到某些人。 - Shaiju T
9
为什么微软会推荐第三方解决方案而不是他们自己的解决方案?他们的措辞非常奇怪:“Json.NET 应该用于序列化和反序列化。为 AJAX 启用的应用程序提供序列化和反序列化功能。” - Protector one
2
提醒一下,如果要引用 System.Web.Extensions,您必须在系统上安装 ASP.NET AJAX 1.0ASP.NET 3.5。请参阅此链接:https://dev59.com/AOo6XIcBkEYKwwoYSCg1 - Sisir
显示剩余4条评论

135

使用Json.Net库,您可以从Nuget Packet Manager下载它。

将对象序列化为Json字符串:

 var obj = new Lad
        {
            firstName = "Markoff",
            lastName = "Chaney",
            dateOfBirth = new MyDate
            {
                year = 1901,
                month = 4,
                day = 30
            }
        };

var jsonString = Newtonsoft.Json.JsonConvert.SerializeObject(obj);

反序列化为对象:

var obj = Newtonsoft.Json.JsonConvert.DeserializeObject<Lad>(jsonString );

71

System.Text.Json 命名空间中提供了一个新的 JSON 序列化程序。它包含在 .NET Core 3.0 共享框架中,针对 .NET Standard 或 .NET Framework 或 .NET Core 2.x 的项目可以使用 NuGet 包

示例代码:

using System;
using System.Text.Json;

public class MyDate
{
    public int year { get; set; }
    public int month { get; set; }
    public int day { get; set; }
}

public class Lad
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public MyDate DateOfBirth { get; set; }
}

class Program
{
    static void Main()
    {
        var lad = new Lad
        {
            FirstName = "Markoff",
            LastName = "Chaney",
            DateOfBirth = new MyDate
            {
                year = 1901,
                month = 4,
                day = 30
            }
        };
        var json = JsonSerializer.Serialize(lad);
        Console.WriteLine(json);
    }
}
在此示例中,要进行序列化的类具有属性而不是字段;System.Text.Json序列化程序目前不会序列化字段。
文档:

附注:(1)为了管理JSON序列化,类的属性必须至少具有getter,(2)JsonSerializer.Serialize(lad)将所有内容打印在一行中;如果您想获得缩进的输出,请使用json options,(3)我宁愿在类本身中重写ToString(),这样您就永远不必再次编写整个JsonSerializer.Serialize(lad)语句,只需在类中放入此内容即可:public override string ToString() => JsonSerializer.Serialize(this, new JsonSerializerOptions { WriteIndented = true }); - Paul Efford

64
使用 DataContractJsonSerializer 类进行操作:MSDN1MSDN2
以下是我的示例代码:这里
JavaScriptSerializer 不同的是,它可以安全地反序列化 JSON 字符串中的对象。但个人更喜欢使用 Json.NET

2
那个页面上仍然看不到任何示例,但是在MSDN其他地方有一些示例->最后一个使用扩展方法实现了一行代码。 - Cristian Diaconescu
4
它不能序列化普通类。报告的错误是“考虑使用DataContractAttribute属性标记它,并使用DataMemberAttribute属性标记您想要序列化的所有成员。如果该类型是集合,请考虑使用CollectionDataContractAttribute进行标记。” - Michael Freidgeim
@Edgar:这就是为什么JavaScriptSerializer更好的原因 :) - Michael Freidgeim
1
@MichaelFreidgeim,哪个更好取决于需求。属性允许您配置属性的序列化方式。 - Edgar
DataContractJsonSerializer非常糟糕,因为它需要为任何类型(例如库对象)设置属性。 - amuliar
显示剩余2条评论

37
你可以通过使用Newtonsoft.json来实现这一点。从NuGet中安装Newtonsoft.json。然后:
using Newtonsoft.Json;

var jsonString = JsonConvert.SerializeObject(obj);

25

哇!使用JSON框架真的更好 :)

这里是我的示例,使用Json.NET (http://james.newtonking.com/json):

using System;
using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json;
using System.IO;

namespace com.blogspot.jeanjmichel.jsontest.model
{
    public class Contact
    {
        private Int64 id;
        private String name;
        List<Address> addresses;

        public Int64 Id
        {
            set { this.id = value; }
            get { return this.id; }
        }

        public String Name
        {
            set { this.name = value; }
            get { return this.name; }
        }

        public List<Address> Addresses
        {
            set { this.addresses = value; }
            get { return this.addresses; }
        }

        public String ToJSONRepresentation()
        {
            StringBuilder sb = new StringBuilder();
            JsonWriter jw = new JsonTextWriter(new StringWriter(sb));

            jw.Formatting = Formatting.Indented;
            jw.WriteStartObject();
            jw.WritePropertyName("id");
            jw.WriteValue(this.Id);
            jw.WritePropertyName("name");
            jw.WriteValue(this.Name);

            jw.WritePropertyName("addresses");
            jw.WriteStartArray();

            int i;
            i = 0;

            for (i = 0; i < addresses.Count; i++)
            {
                jw.WriteStartObject();
                jw.WritePropertyName("id");
                jw.WriteValue(addresses[i].Id);
                jw.WritePropertyName("streetAddress");
                jw.WriteValue(addresses[i].StreetAddress);
                jw.WritePropertyName("complement");
                jw.WriteValue(addresses[i].Complement);
                jw.WritePropertyName("city");
                jw.WriteValue(addresses[i].City);
                jw.WritePropertyName("province");
                jw.WriteValue(addresses[i].Province);
                jw.WritePropertyName("country");
                jw.WriteValue(addresses[i].Country);
                jw.WritePropertyName("postalCode");
                jw.WriteValue(addresses[i].PostalCode);
                jw.WriteEndObject();
            }

            jw.WriteEndArray();

            jw.WriteEndObject();

            return sb.ToString();
        }

        public Contact()
        {
        }

        public Contact(Int64 id, String personName, List<Address> addresses)
        {
            this.id = id;
            this.name = personName;
            this.addresses = addresses;
        }

        public Contact(String JSONRepresentation)
        {
            //To do
        }
    }
}

测试:

using System;
using System.Collections.Generic;
using com.blogspot.jeanjmichel.jsontest.model;

namespace com.blogspot.jeanjmichel.jsontest.main
{
    public class Program
    {
        static void Main(string[] args)
        {
            List<Address> addresses = new List<Address>();
            addresses.Add(new Address(1, "Rua Dr. Fernandes Coelho, 85", "15º andar", "São Paulo", "São Paulo", "Brazil", "05423040"));
            addresses.Add(new Address(2, "Avenida Senador Teotônio Vilela, 241", null, "São Paulo", "São Paulo", "Brazil", null));

            Contact contact = new Contact(1, "Ayrton Senna", addresses);

            Console.WriteLine(contact.ToJSONRepresentation());
            Console.ReadKey();
        }
    }
}

结果:

{
  "id": 1,
  "name": "Ayrton Senna",
  "addresses": [
    {
      "id": 1,
      "streetAddress": "Rua Dr. Fernandes Coelho, 85",
      "complement": "15º andar",
      "city": "São Paulo",
      "province": "São Paulo",
      "country": "Brazil",
      "postalCode": "05423040"
    },
    {
      "id": 2,
      "streetAddress": "Avenida Senador Teotônio Vilela, 241",
      "complement": null,
      "city": "São Paulo",
      "province": "São Paulo",
      "country": "Brazil",
      "postalCode": null
    }
  ]
}

现在我将实现构造函数方法,该方法将接收一个JSON字符串并填充类的字段。


1
好的帖子,这是最新的做法。 - MatthewD
1
我猜想人们期望在“测试”部分找到一个单元测试,但实际上并没有。顺便说一下,我喜欢Contact对象知道如何将自己转换为JSON的方法。但是我不喜欢这个例子中的对象实际上并不是面向对象编程(OOP)的对象,而只是一堆公共方法和属性。 - Artur INTECH
"com.blogspot.jeanjmichel.jsontest.main" 啊,一个 Java 程序员走向了黑暗面。欢迎加入我们。我们有饼干。 - Corey
嘿嘿嘿嘿,是的@Corey =) - Jean J. Michel

10

如果它们不是很大,那么您可能需要将其导出为JSON格式。同时,这可以使其在所有平台上都具有可移植性。

using Newtonsoft.Json;

[TestMethod]
public void ExportJson()
{
    double[,] b = new double[,]
        {
            { 110,  120,  130,  140, 150 },
            {1110, 1120, 1130, 1140, 1150},
            {1000,    1,   5,     9, 1000},
            {1110,    2,   6,    10, 1110},
            {1220,    3,   7,    11, 1220},
            {1330,    4,   8,    12, 1330}
        };

    string jsonStr = JsonConvert.SerializeObject(b);

    Console.WriteLine(jsonStr);

    string path = "X:\\Programming\\workspaceEclipse\\PyTutorials\\src\\tensorflow_tutorials\\export.txt";

    File.WriteAllText(path, jsonStr);
}

8
如果你在一个ASP.NET MVC网络控制器中,只需要这样简单的代码:
string ladAsJson = Json(Lad);

难以置信没有人提到这个。


1
我收到一个关于无法将JsonResult转换为字符串的错误。 - csga5000
它将以隐式类型编译:var ladAsJson = Json(Lad)。 - ewomack

7

使用内置的System.Text.Json(.NET Core 3.0+)提供另一种解决方案,其中对象是自给自足的,不会暴露所有可能的字段:

通过测试:

using NUnit.Framework;

namespace Intech.UnitTests
{
    public class UserTests
    {
        [Test]
        public void ConvertsItselfToJson()
        {
            var userName = "John";
            var user = new User(userName);

            var actual = user.ToJson();

            Assert.AreEqual($"{{\"Name\":\"{userName}\"}}", actual);
        }
    }
}

一个实现:

using System.Text.Json;
using System.Collections.Generic;

namespace Intech
{
    public class User
    {
        private readonly string name;

        public User(string name)
        {
            this.name = name;
        }

        public string ToJson()
        {
            var params = new Dictionary<string, string>{{"Name", name}};
            return JsonSerializer.Serialize(params);
        }
    }
}

我必须在未连接互联网的虚拟机中编写代码,因此这非常有用。 - TomDestry

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接