如何使用C#解析JSON?


455

我有以下代码:

var user = (Dictionary<string, object>)serializer.DeserializeObject(responsecontent);

输入的responsecontent是JSON,但未正确解析为对象。如何正确反序列化?



34
JsonSystem.Web.Helpers,有JsonQueryStringConverterSystem.ServiceModel.Web,有JavascriptSerializerSystem.Web.Script.SerializationDataContractJsonSerializerSystem.Runtime.Serialization.Json,赫克MS甚至已经决定将包括第三方Json.NET公司的ASP.NET Web的API中。如果您认为这还不够,那就是MS正在提出,System.Json但目前不适合使用。走的路Microsoft走的路。...我选择外观最好的命名空间。
nawfal 2015年

4
@fusi其余的都在单独的程序集中。Google的名称空间/类名称,您将在msdn文档中找到它们的程序集。只需添加对该程序集的引用即可。
nawfal 2015年

1
只是为了完成,也有JsonValueWindows.Data.Json这仅适用于Windows 8及以上。我喜欢这个。MS正在执行任务:)
nawfal

5
NewtonSoft在他们的网站上有一个比较页面(可能有偏见,但仍然很有趣):newtonsoft.com/json/help/html/jsonnetvsdotnetserializers.htm。我特别喜欢“ 无意义”词典的序列化行:)
Ohad Schneider

Answers:


365

我假设您没有使用Json.NET(Newtonsoft.Json NuGet包)。如果是这种情况,那么您应该尝试一下。

它具有以下功能:

  1. LINQ转JSON
  2. JsonSerializer,用于将.NET对象快速转换为JSON并再次转换回
  3. Json.NET可以选择生成格式正确的缩进JSON以进行调试或显示
  4. 可以将JsonIgnore和JsonProperty之类的属性添加到类中,以自定义类的序列化方式
  5. 能够将JSON与XML相互转换
  6. 支持多种平台:.NET,Silverlight和Compact Framework

看下面的例子。在此示例中,JsonConvert类用于将对象与JSON相互转换。为此,它有两种静态方法。他们是SerializeObject(Object obj)DeserializeObject<T>(String json)

Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };

string json = JsonConvert.SerializeObject(product);
//{
//  "Name": "Apple",
//  "Expiry": "2008-12-28T00:00:00",
//  "Price": 3.99,
//  "Sizes": [
//    "Small",
//    "Medium",
//    "Large"
//  ]
//}

Product deserializedProduct = JsonConvert.DeserializeObject<Product>(json);

18
var如果我不知道目标的完整结构,我可以反序列化为类型变量吗?具体来说,我正在使用Rally用户故事,并且想将它们转换为对象。
Pedro Dusso 2013年

16
@VANDERWEYENJonathan-在现代的Web浏览器中,JSON.parse(string)和JSON.stringify(object)都将日期作为ISO8601字符串处理,这是上述答案中描述的格式。您可能想在人们认为不相关的标准之前对其进行更新。人们需要日期比他们需要的标准多得多。
Peter Wone 2014年

3
@PeterWone:不,JSON.parse('{"Expiry": "2008-12-28T00:00:00"}').Expiry返回字符串 "2008-12-28T00:00:00",而不是日期。可以将其转换Datevia new Date(str),但JSON.parse对日期一无所知。您必须传递一个reviver,该reviver会根据模式检查每个字符串值。
TJ人群

3
因为3.703秒与3s和703ms相同,并且分隔符是小数点,所以我认为这是秒到小数点后三位。
Peter Wone

38
为什么每个人都具有这样的问题,包括相关的requireincludeimportusing在他们的回答语句。那一条线会痛吗?
托马什Zato -恢复莫妮卡

284

正如这里回答的那样-将JSON反序列化为C#动态对象?

使用Json.NET非常简单:

dynamic stuff = JsonConvert.DeserializeObject("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");

string name = stuff.Name;
string address = stuff.Address.City;

或使用Newtonsoft.Json.Linq:

dynamic stuff = JObject.Parse("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");

string name = stuff.Name;
string address = stuff.Address.City;

13
@MaxHodges,你是对的。我只是使用内联“魔术字符串”来演示如何解析JSON字符串值。不想用转义双引号使它看起来复杂。在实际代码中,我们通常将JSON字符串从某处获取为变量或作为参数传递。
德米特里·帕夫洛夫

4
没有.net 4,您将没有'dynamic'关键字。您可以使用'var stuff'进行声明,而不是'stuff.Name'和'stuff.Address.City',而分别具有'stuff [“ Name”]'和'stuff [“ Address”] [“ City”]' 。
费尔

1
@Fil为您提供type的值object,并且您不能在上使用索引object
Alex

138

以下是一些使用第三方库的选项:

// For that you will need to add reference to System.Runtime.Serialization
var jsonReader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(@"{ ""Name"": ""Jon Smith"", ""Address"": { ""City"": ""New York"", ""State"": ""NY"" }, ""Age"": 42 }"), new System.Xml.XmlDictionaryReaderQuotas());

// For that you will need to add reference to System.Xml and System.Xml.Linq
var root = XElement.Load(jsonReader);
Console.WriteLine(root.XPathSelectElement("//Name").Value);
Console.WriteLine(root.XPathSelectElement("//Address/State").Value);

// For that you will need to add reference to System.Web.Helpers
dynamic json = System.Web.Helpers.Json.Decode(@"{ ""Name"": ""Jon Smith"", ""Address"": { ""City"": ""New York"", ""State"": ""NY"" }, ""Age"": 42 }");
Console.WriteLine(json.Name);
Console.WriteLine(json.Address.State);

请参阅链接以获取有关System.Web.Helpers.Json的更多信息。

更新:如今,最简单的方法Web.Helpers是使用NuGet软件包


如果您不关心早期的Windows版本,则可以使用Windows.Data.Json名称空间的类:

// minimum supported version: Win 8
JsonObject root = Windows.Data.Json.JsonValue.Parse(jsonString).GetObject();
Console.WriteLine(root["Name"].GetString());
Console.WriteLine(root["Address"].GetObject()["State"].GetString());

为什么我在ASP.NET网站(4.5)中看不到System.Web.Helpers?XElement,XPathSelectElement对于我的VisualStudio未知。如何教育呢?
2014年

好了,您必须添加相应库的引用(如上面的注释中所述),有关更多信息,请参见本文。同样,这个问题可能很有趣。
qqbenq 2014年

2
我使用了此处介绍的Web.Helpers方法,但遇到了一个问题,此问题已解决:stackoverflow.com/questions/7066726/…–
Alex

1
它与WPF一起使用。通过使用System.Runtime.Serialization.Json使用以下名称空间;使用System.Xml.XPath; 使用System.Xml.Linq;
Shahid Neermunda '16


62

如果您可以使用.NET 4,请查看:http : //visitmix.com/writings/the-rise-of-json(archive.org)

这是该网站的摘录:

WebClient webClient = new WebClient();
dynamic result = JsonValue.Parse(webClient.DownloadString("https://api.foursquare.com/v2/users/self?oauth_token=XXXXXXX"));
Console.WriteLine(result.response.user.firstName);

最后一个Console.WriteLine很不错...


抱歉,自从我最初回答以来,情况似乎已发生变化。我必须四处看看,看看哪个库是正确的...
ElonU Webdev 2012年

7
期待您找到该库。编辑:这是一个:dynamicjson.codeplex.com吗?
user989056 2012年

1
我不知道ElonU在这里是什么类,但是Windows.Data.Json(仅适用于Windows 8和更高版本-很奇怪)中有“ JsonValue”,而System.Json中也有“ JsonValue”,尚在预览和只有上帝知道它是否会出现。在谈到Json时,MS使我感到困惑。
nawfal

35

另一个本机解决方案,不需要任何第三方库,但对System.Web.Extensions的引用是JavaScriptSerializer。自3.5以来,这不是一个新功能,而是一个非常未知的内置功能。

using System.Web.Script.Serialization;

..

JavaScriptSerializer serializer = new JavaScriptSerializer();
objectString = serializer.Serialize(new MyObject());

然后回来

MyObject o = serializer.Deserialize<MyObject>(objectString)

2
这非常好,但是它需要Web组件,因此不幸的是,它在.NET 4.0 Client Profile(Windows XP的最新.NET版本)中不起作用。可以完全安装.NET,但是许多人坚持使用Client Profile。相反,即使在Client Profile中,也支持System.Runtime.Serialization.Json.DataContractJsonSerializer。
Al Kepp

3
@ fr34kyn01535:Windows XP在台式机上占有第二大市场份额。这是相关的。
DonkeyMaster 2015年

当我使用JavaScriptSerializer反序列化我的对象时,它可以工作,但是却错误地反序列化了我的日期。它应该是4/19/2018 12:00 AM,但反序列化到4/18/2018 08:00 PM。NewtonSoft.Json.JsonConvert按预期反序列化了它。
Rich


16

System.Json现在可以工作...

安装nuget https://www.nuget.org/packages/System.Json

PM> Install-Package System.Json -Version 4.5.0

样品

// PM>Install-Package System.Json -Version 4.5.0

using System;
using System.Json;

namespace NetCoreTestConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            // Note that JSON keys are case sensitive, a is not same as A.

            // JSON Sample
            string jsonString = "{\"a\": 1,\"b\": \"string value\",\"c\":[{\"Value\": 1}, {\"Value\": 2,\"SubObject\":[{\"SubValue\":3}]}]}";

            // You can use the following line in a beautifier/JSON formatted for better view
            // {"a": 1,"b": "string value","c":[{"Value": 1}, {"Value": 2,"SubObject":[{"SubValue":3}]}]}

            /* Formatted jsonString for viewing purposes:
            {
               "a":1,
               "b":"string value",
               "c":[
                  {
                     "Value":1
                  },
                  {
                     "Value":2,
                     "SubObject":[
                        {
                           "SubValue":3
                        }
                     ]
                  }
               ]
            }
            */

            // Verify your JSON if you get any errors here
            JsonValue json = JsonValue.Parse(jsonString);

            // int test
            if (json.ContainsKey("a"))
            {
                int a = json["a"]; // type already set to int
                Console.WriteLine("json[\"a\"]" + " = " + a);
            }

            // string test
            if (json.ContainsKey("b"))
            {
                string b = json["b"];  // type already set to string
                Console.WriteLine("json[\"b\"]" + " = " + b);
            }

            // object array test
            if (json.ContainsKey("c") && json["c"].JsonType == JsonType.Array)
            {
                // foreach loop test
                foreach (JsonValue j in json["c"])
                {
                    Console.WriteLine("j[\"Value\"]" + " = " + j["Value"].ToString());
                }

                // multi level key test
                Console.WriteLine("json[\"c\"][0][\"Value\"]" + " = " + json["c"][0]["Value"].ToString());
                Console.WriteLine("json[\"c\"][0][\"Value\"]" + " = " + json["c"][1]["Value"].ToString());
                Console.WriteLine("json[\"c\"][1][\"SubObject\"][0][\"SubValue\"]" + " = " + json["c"][1]["SubObject"][0]["SubValue"].ToString());
            }

            Console.WriteLine();
            Console.Write("Press any key to exit.");
            Console.ReadKey();
        }
    }
}

1
试图找到一个如何正确使用现代System.Json的示例,此前无数Json.NET/Newtonsoft.Json/"Newtson.Json“的结果以及System.Json的较早版本早已弃用。这次真是万分感谢。
monkey0506 '19

1
这极大地帮助了我。非常感谢你。
MAK

10

使用此工具生成基于您的json的类:

http://json2csharp.com/

然后使用该类反序列化您的json。例:

public class Account
{
    public string Email { get; set; }
    public bool Active { get; set; }
    public DateTime CreatedDate { get; set; }
    public IList<string> Roles { get; set; }
}


string json = @"{
  'Email': 'james@example.com',
  'Active': true,
  'CreatedDate': '2013-01-20T00:00:00Z',
  'Roles': [
    'User',
    'Admin'
  ]
}";

Account account = JsonConvert.DeserializeObject<Account>(json);

Console.WriteLine(account.Email);
// james@example.com

参考:https : //forums.asp.net/t/1992996.aspx ? Nested+ Json+ Deserialization+ to+C+ object+ and+ using+ that+ object https://www.newtonsoft.com/json/help /html/DeserializeObject.htm


9

尝试以下代码:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("URL");
JArray array = new JArray();
using (var twitpicResponse = (HttpWebResponse)request.GetResponse())
using (var reader = new StreamReader(twitpicResponse.GetResponseStream()))
{
    JavaScriptSerializer js = new JavaScriptSerializer();
    var objText = reader.ReadToEnd();

    JObject joResponse = JObject.Parse(objText);
    JObject result = (JObject)joResponse["result"];
    array = (JArray)result["Detail"];
    string statu = array[0]["dlrStat"].ToString();
}

谢谢,我想要[“ result” + variable]部分,因为我想在这里使用变量,而JSON.NET很难做到这一点。
PHPGuru

这行代码有什么作用吗?JavaScriptSerializer js = new JavaScriptSerializer(); 提前致谢。
克里斯·卡蒂尼亚尼

9

系统文本

.NET core 3.0带有System.Text.Json内置功能,这意味着您可以在使用第三方库的情况下反序列化/序列化JSON 。

要将您的类序列化为JSON字符串:

var json = JsonSerializer.Serialize(order);

要将JSON反序列化为强类型类:

var order = JsonSerializer.Deserialize<Order>(json);

因此,如果您有一个像下面这样的课程:

public class Order
{
    public int Id { get; set; }
    public string OrderNumber { get; set; }
    public decimal Balance { get; set; }
    public DateTime Opened { get; set; }
}

var json = JsonSerializer.Serialize(order);
// creates JSON ==>
{
    "id": 123456,
    "orderNumber": "ABC-123-456",
    "balance": 9876.54,
    "opened": "2019-10-21T23:47:16.85",
};

var order = JsonSerializer.Deserialize<Order>(json);
// ==> creates the above class

需要注意的一件事是,使用自己的代码时System.Text.Json 不会自动处理camelCaseJSON属性(但是,使用MVC / WebAPI请求和模型绑定程序时会自动处理)。

要解决此问题,您需要将其JsonSerializerOptions作为参数传递。

JsonSerializerOptions options = new JsonSerializerOptions
{        
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,  // set camelCase       
    WriteIndented = true                                // write pretty json
};

// pass options to serializer
var json = JsonSerializer.Serialize(order, options);
// pass options to deserializer
var order = JsonSerializer.Deserialize<Order>(json, options);

System.Text.Json也可作为Nu-get包System.Text.Json用于.Net Framework和.Net Standard。


1
如果您没有课程怎么办?如果您仅隐约知道json数据将包含什么怎么办?还是这些键根本不存在?
Cherona

@Cherona使用JsonDocument.Parse
haldo

5

我认为msdn站点上的以下内容应为您所寻找的内容提供一些本机功能。请注意,它是为Windows 8指定的。下面列出了该站点的一个示例。

JsonValue jsonValue = JsonValue.Parse("{\"Width\": 800, \"Height\": 600, \"Title\": \"View from 15th Floor\", \"IDs\": [116, 943, 234, 38793]}");
double width = jsonValue.GetObject().GetNamedNumber("Width");
double height = jsonValue.GetObject().GetNamedNumber("Height");
string title = jsonValue.GetObject().GetNamedString("Title");
JsonArray ids = jsonValue.GetObject().GetNamedArray("IDs");

它利用Windows.Data.JSON命名空间。


6
不错,但是“最低支持的客户端:Windows 8”
watbywbarif

我认为它不再受支持,现在有newtonsoft json dll icouldnt找到windows.data.json
virtouso 2015年

3
@virtouso,如watbywbarif指出,这实际上是从比较新,但是最小支持微软,仅适用于Windows 8的内
TargetofGravity

3

您可以使用以下扩展

public static class JsonExtensions
{
    public static T ToObject<T>(this string jsonText)
    {
        return JsonConvert.DeserializeObject<T>(jsonText);
    }

    public static string ToJson<T>(this T obj)
    {
        return JsonConvert.SerializeObject(obj);
    } 
}

0

我认为我看到的最好的答案是@MD_Sayem_Ahmed。

您的问题是“如何使用C#解析Json”,但似乎您想解码Json。如果您想对其进行解码,那么艾哈迈德的答案很好。

如果您试图在ASP.NET Web Api中完成此操作,最简单的方法是创建一个数据传输对象,该对象包含要分配的数据:

public class MyDto{
    public string Name{get; set;}
    public string Value{get; set;}
}

您只需将application / json标头添加到您的请求中(例如,如果您使用的是Fiddler)。然后,您将在ASP.NET Web API中使用它,如下所示:

//controller method -- assuming you want to post and return data
public MyDto Post([FromBody] MyDto myDto){
   MyDto someDto = myDto;
   /*ASP.NET automatically converts the data for you into this object 
    if you post a json object as follows:
{
    "Name": "SomeName",
      "Value": "SomeValue"
}
*/
   //do some stuff
}

当我在Web Api中工作时,这对我很有帮助,并使我的生活变得异常轻松。


0
         string json = @"{
            'Name': 'Wide Web',
            'Url': 'www.wideweb.com.br'}";

        JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
        dynamic j = jsonSerializer.Deserialize<dynamic>(json);
        string name = j["Name"].ToString();
        string url = j["Url"].ToString();

-1
var result = controller.ActioName(objParams);
IDictionary<string, object> data = (IDictionary<string, object>)new System.Web.Routing.RouteValueDictionary(result.Data);
Assert.AreEqual("Table already exists.", data["Message"]);

2
您可以更好地解释您的解决方案,而不仅仅是发布一些代码。您可能会读到《我如何写一个好的答案》
Massimiliano Kraus's

别忘了System.Web在项目参考中包含这些内容。
奥哈德·科恩

-3
 using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(user)))
 {
    // Deserialization from JSON  
    DataContractJsonSerializer deserializer = new DataContractJsonSerializer(typeof(UserListing))
    DataContractJsonSerializer(typeof(UserListing));
    UserListing response = (UserListing)deserializer.ReadObject(ms);

 }

 public class UserListing
 {
    public List<UserList> users { get; set; }      
 }

 public class UserList
 {
    public string FirstName { get; set; }       
    public string LastName { get; set; } 
 }
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.