简体   繁体   English

如何用 C# 反序列化 JSON?

[英]How can I deserialize JSON with C#?

I have the following code:我有以下代码:

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

The input in responsecontent is JSON, but it is not properly deserialized into an object. How should I properly deserialize it? responsecontent中的输入是 JSON,但没有正确反序列化为 object。我应该如何正确反序列化它?

I am assuming you are not using Json.NET (Newtonsoft.Json NuGet package).我假设您没有使用Json.NET (Newtonsoft.Json NuGet 包)。 If this the case, then you should try it.如果是这种情况,那么您应该尝试一下。

It has the following features:它具有以下特点:

  1. LINQ to JSON LINQ 到 JSON
  2. The JsonSerializer for quickly converting your .NET objects to JSON and back again JsonSerializer 用于快速将您的 .NET 对象转换为 JSON 并再次转换回来
  3. Json.NET can optionally produce well formatted, indented JSON for debugging or display Json.NET 可以选择生成格式良好、缩进的 JSON 用于调试或显示
  4. Attributes like JsonIgnore and JsonProperty can be added to a class to customize how a class is serialized可以将JsonIgnoreJsonProperty等属性添加到 class 以自定义 class 的序列化方式
  5. Ability to convert JSON to and from XML能够将 JSON 与 XML 相互转换
  6. Supports multiple platforms: .NET, Silverlight and the Compact Framework支持多种平台:.NET、Silverlight 和 Compact Framework

Look at the example below.看下面的例子 In this example, JsonConvert class is used to convert an object to and from JSON.在此示例中, JsonConvert class 用于在 object 与 JSON 之间进行转换。 It has two static methods for this purpose.为此,它有两个 static 方法。 They are SerializeObject(Object obj) and DeserializeObject<T>(String json) :它们是SerializeObject(Object obj)DeserializeObject<T>(String json)

using Newtonsoft.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);

As was answered here - Deserialize JSON into C# dynamic object?正如这里回答的那样 -将 JSON 反序列化为 C# 动态 object?

It's pretty simple using Json.NET:使用 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;

Or using Newtonsoft.Json.Linq:或使用 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;

Here are some options without using third party libraries:以下是一些使用第三方库的选项:

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

See the link for more information about System.Web.Helpers.Json .有关System.Web.Helpers.Json的更多信息,请参阅链接。

Update : Nowadays the easiest way to get the Web.Helpers is to use the NuGet package .更新:如今获得Web.Helpers的最简单方法是使用NuGet package


If you don't care about earlier windows versions you can use the classes of the Windows.Data.Json namespace:如果您不关心早期的 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());

If .NET 4 is available to you, check out: http://visitmix.com/writings/the-rise-of-json (archive.org)如果 .NET 4 可供您使用,请查看: http://visitmix.com/writings/the-rise-of-json (archive.org)

Here is a snippet from that site:这是该网站的一个片段:

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

That last Console.WriteLine is pretty sweet...最后一个 Console.WriteLine 很可爱...

Another native solution to this, which doesn't require any 3rd party libraries but a reference to System.Web.Extensions is the JavaScriptSerializer. JavaScriptSerializer 是另一个本机解决方案,它不需要任何第三方库,而是引用System.Web.Extensions This is not a new but a very unknown built-in features there since 3.5.自 3.5 以来,这不是一个新的但非常未知的内置功能。

using System.Web.Script.Serialization;

.. ..

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

and back然后回来

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

System.Text.Json System.Text.Json

.NET core 3.0 comes with System.Text.Json built-in which means you can deserialize/serialize JSON without using a third-party library. .NET core 3.0 自带System.Text.Json内置,这意味着您可以在使用第三方库的情况下反序列化/序列化 JSON。

Serialize/Deserialize序列化/反序列化

To serialize your class(es) to JSON string:要将您的类序列化为 JSON 字符串:

var json = JsonSerializer.Serialize(model);

To deserialize the JSON into a strongly typed class:要将 JSON 反序列化为强类型 class:

var model = JsonSerializer.Deserialize<Model>(json);

Parse (.NET 6)解析(.NET 6)

.NET 6 introduced the System.Text.Json.Nodes namespace which enables DOM parsing, navigation and manipulation in a similar manner to Newtonsoft.Json using the new classes JsonObject , JsonArray , JsonValue , and JsonNode . .NET 6 introduced the System.Text.Json.Nodes namespace which enables DOM parsing, navigation and manipulation in a similar manner to Newtonsoft.Json using the new classes JsonObject , JsonArray , JsonValue , and JsonNode .

// JsonObject parse DOM
var jsonObject = JsonNode.Parse(jsonString).AsObject();
// read data from DOM
string name = jsonObject["Name"].ToString();
DateTime date = (DateTime)jsonObject["Date"];
var people = jsonObject["People"].Deserialize<List<Person>>();

Similar methods apply to JsonArray .类似的方法适用于JsonArray This answer provides more details on JsonObject.答案提供了有关 JsonObject 的更多详细信息。


One thing to note is that System.Text.Json does not automatically handle camelCase JSON properties when using your own code (however, it does when using MVC/WebAPI requests and the model binder).需要注意的一点是System.Text.Json在使用您自己的代码时不会自动处理camelCase JSON 属性(但是,在使用 MVC/WebAPI 请求和 Z20F35E630DAF454DBFA4C3F8Z 绑定器时会自动处理)。

To resolve this you need to pass JsonSerializerOptions as a parameter.要解决此问题,您需要将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 is also available for.Net Framework and.Net Standard as a Nu-get package System.Text.Json System.Text.Json也可用于 .Net Framework 和 .Net Standard 作为 Nu-get package System.Text.Json

You could also have a look at the DataContractJsonSerializer你也可以看看DataContractJsonSerializer

System.Json works now... System.Json 现在可以工作了...

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

PM> Install-Package System.Json -Version 4.5.0

Sample :样品

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

Try the following code:试试下面的代码:

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

Use this tool to generate a class based in your json:使用此工具生成基于 json 的 class:

http://json2csharp.com/ http://json2csharp.com/

And then use the class to deserialize your json.然后使用 class 反序列化您的 json。 Example:例子:

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

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

If JSON is dynamic as below如果 JSON 是动态的,如下所示

{
 "Items": [{
        "Name": "Apple",
        "Price": 12.3
    },
    {
        "Name": "Grape",
        "Price": 3.21
    }
   ],
   "Date": "21/11/2010"
}

Then, Once you install NewtonSoft.Json from NuGet and include it in your project, you can serialize it as然后,一旦从 NuGet 安装NewtonSoft.Json并将其包含在您的项目中,您可以将其序列化为

string jsonString = "{\"Items\": [{\"Name\": \"Apple\",\"Price\": 12.3},{\"Name\": \"Grape\",\"Price\": 3.21}],\"Date\": \"21/11/2010\"}";

        dynamic DynamicData = JsonConvert.DeserializeObject(jsonString);

        Console.WriteLine(   DynamicData.Date); // "21/11/2010"
        Console.WriteLine(DynamicData.Items.Count); // 2
        Console.WriteLine(DynamicData.Items[0].Name); // "Apple"

Source: How to read JSON data in C# (Example using Console app & ASP.NET MVC)?资料来源: 如何读取 C# 中的 JSON 数据(使用控制台应用程序和 ASP.NET MVC 的示例)?

The following from the msdn site should I think help provide some native functionality for what you are looking for.我认为来自msdn站点的以下内容应该有助于为您正在寻找的内容提供一些本机功能。 Please note it is specified for Windows 8. One such example from the site is listed below.请注意,它是为 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");

It utilizes the Windows.Data.JSON namespace.它利用Windows.Data.JSON命名空间。

You can use following extentions您可以使用以下扩展

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

I ended up with a simple class that creates types on the fly, instantiate them and hydrate them, mirroring the structure of the input JSON.我最终得到了一个简单的 class,它可以动态创建类型、实例化它们并水合它们,镜像输入 JSON 的结构。

在此处输入图像描述

You can find it here:你可以在这里找到它:

https://github.com/starnutoditopo/JsonToObject https://github.com/starnutoditopo/JsonToObject

Here's a complete, runnable example using csc v2.0.0.61501.这是一个完整的、可运行的示例,使用csc v2.0.0.61501。

Packages:套餐:

nuget install Microsoft.AspNet.WebApi.Core
nuget install Microsoft.Net.Http
nuget install Newtonsoft.Json

Code:代码:

using Newtonsoft.Json;
using System;
using System.Net.Http;
using System.Threading.Tasks;

public static class App
{
    static void Main()
    {
        MainAsync().GetAwaiter().GetResult();
    }

    static async Task MainAsync()
    {
        string url = "https://httpbin.org/get";
        var client = new HttpClient();

        // The verbose way:
        //HttpResponseMessage response = await client.GetAsync(url);
        //response.EnsureSuccessStatusCode();
        //string responseBody = await response.Content.ReadAsStringAsync();

        // Or:
        string responseBody = await client.GetStringAsync(url);

        var obj = JsonConvert.DeserializeObject<dynamic>(responseBody);
        Console.WriteLine(obj);
        Console.WriteLine(obj.headers.Host);
    }
}

Compiler command:编译命令:

 csc http_request2.cs -r:".\Microsoft.AspNet.WebApi.Core.5.2.9\lib\net45\System.Web.Http.dll" -r:".\Microsoft.Net.Http.2.2.29\lib\net40\System.Net.Http.dll" -r:".\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll"

Output: Output:

{
  "args": {},
  "headers": {
    "Host": "httpbin.org",
    "X-Amzn-Trace-Id": "Root=1-633dce52-64f923bb42c99bf46f78672c"
  },
  "origin": "98.51.7.199",
  "url": "https://httpbin.org/get"
}
httpbin.org

Per Could not load file or assembly Newtonsoft.json.无法加载文件或程序集 Newtonsoft.json。 The system cannot find the file specified , I had to move the Newtonsoft.Json.dll next to the compiled binary. 系统找不到指定的文件,我只好将Newtonsoft.Json.dll移到编译后的二进制文件旁边。

I think the best answer that I've seen has been @MD_Sayem_Ahmed.我认为我见过的最好的答案是@MD_Sayem_Ahmed。

Your question is "How can I parse Json with C#", but it seems like you are wanting to decode Json.您的问题是“如何使用 C# 解析 Json”,但您似乎想要解码 Json。 If you are wanting to decode it, Ahmed's answer is good.如果您想对其进行解码,艾哈迈德的回答很好。

If you are trying to accomplish this in ASP.NET Web Api, the easiest way is to create a data transfer object that holds the data you want to assign: If you are trying to accomplish this in ASP.NET Web Api, the easiest way is to create a data transfer object that holds the data you want to assign:

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

You have simply add the application/json header to your request (if you are using Fiddler, for example).您只需将 application/json header 添加到您的请求中(例如,如果您使用的是 Fiddler)。 You would then use this in ASP.NET Web API as follows:然后,您将在 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
}

This helped me a lot when I was working in my Web Api and made my life super easy.当我在 Web Api 工作时,这对我有很大帮助,让我的生活变得超级轻松。

         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();
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"]);
 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; } 
 }

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

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