使用C#反序列化JSON

244

我正在尝试将Facebook好友的Graph API调用反序列化为对象列表。JSON对象长这样:

{"data":[{"id":"518523721","name":"ftyft"},
         {"id":"527032438","name":"ftyftyf"},
         {"id":"527572047","name":"ftgft"},
         {"id":"531141884","name":"ftftft"},
         {"id":"532652067","name"...

List<EFacebook> facebooks = new JavaScriptSerializer().Deserialize<List<EFacebook>>(result);

因为原始对象无效,所以它不能正常工作。我该如何反序列化它?


3
请提供原文所在的句子或上下文以便更好地翻译。 - ashutosh raina
2
您可以使用Dictionary<string,string>,请参考:https://dev59.com/VFzUa4cB1Zd3GeqPzQsw#7701070 - Kakashi
14
你的朋友发给你一个链接:http://json2csharp.com/。 该网站提供将JSON格式数据转换为C#类代码的工具。 - nawfal
6
实际上,Visual Studio (2013版或安装了 Web 工具的 2012 版)已经内置了这个功能:编辑 > 粘贴特殊 > 以类形式粘贴 JSON。 - floomby
10个回答

296

您需要创建这样的结构:

public class Friends
{

    public List<FacebookFriend> data {get; set;}
}

public class FacebookFriend
{

    public string id {get; set;}
    public string name {get; set;}
}

那么你应该能够执行:

Friends facebookFriends = new JavaScriptSerializer().Deserialize<Friends>(result);
我的类的名称只是一个示例。您应该使用适当的名称。
添加一个示例测试:
string json =
    @"{""data"":[{""id"":""518523721"",""name"":""ftyft""}, {""id"":""527032438"",""name"":""ftyftyf""}, {""id"":""527572047"",""name"":""ftgft""}, {""id"":""531141884"",""name"":""ftftft""}]}";

Friends facebookFriends = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<Friends>(json);

foreach(var item in facebookFriends.data)
{
    Console.WriteLine("id: {0}, name: {1}", item.id, item.name);
}

输出:

id: 518523721, name: ftyft
id: 527032438, name: ftyftyf
id: 527572047, name: ftgft
id: 531141884, name: ftftft

3
是的,我不想创建一个新对象来持有子对象。我想我会从 JSON 中提取出原始对象。谢谢。 - user989818
@Kevin Holditch,感谢您的纠正。我漏掉了一个重要的部分 :) - Icarus
2
我不喜欢 System.Web.Script.Serialization.JavaScriptSerializer() 的地方在于你总是需要一个定义好的类型 T。而在 Java 中,有一个名为 org.java 的库(包)可以保持匿名:“JSONObject["param"].JSONarray(5)”等。 - sports
2
需要注意的是,id和name属性的setter必须保持public。如果将它们设置为private或protected,反序列化将会执行而不报错,但所有数据都将为空。 - Isaac Zais
2
@ sports,你可以通过将反序列化为动态类型来实现C#,但如果你将其反序列化为已知类型,则性能会更好。 - PRMan

58

有时候我更喜欢动态对象:

public JsonResult GetJson()
{
  string res;
  WebClient client = new WebClient();

  // Download string
  string value = client.DownloadString("https://api.instagram.com/v1/users/000000000/media/recent/?client_id=clientId");

  // Write values
  res = value;
  dynamic dyn = JsonConvert.DeserializeObject(res);
  var lstInstagramObjects = new List<InstagramModel>();

  foreach(var obj in dyn.data)
  {
    lstInstagramObjects.Add(new InstagramModel()
    {
      Link = (obj.link != null) ? obj.link.ToString() : "",
      VideoUrl = (obj.videos != null) ? obj.videos.standard_resolution.url.ToString() : "",
      CommentsCount = int.Parse(obj.comments.count.ToString()),
      LikesCount = int.Parse(obj.likes.count.ToString()),
      CreatedTime = new System.DateTime(1970, 1, 1, 0, 0, 0, 0).AddSeconds((double.Parse(obj.created_time.ToString()))),
      ImageUrl = (obj.images != null) ? obj.images.standard_resolution.url.ToString() : "",
      User = new InstagramModel.UserAccount()
             {
               username = obj.user.username,
               website = obj.user.website,
               profile_picture = obj.user.profile_picture,
               full_name = obj.user.full_name,
               bio = obj.user.bio,
               id = obj.user.id
             }
    });
  }

  return Json(lstInstagramObjects, JsonRequestBehavior.AllowGet);
}

一个使用这种方法非常有用的例子是,当我尝试将对象反序列化为包含接口属性的对象时。 - soupy1976
3
需要解释一下。 - Peter Mortensen
1
你为什么更喜欢这个答案而不是@Icarus的被接受的答案? - Questioning
@Questioning,将反序列化为强类型类会忽略任何不在您的类中的属性,而将反序列化为动态对象只会返回灵活适应未来任何新属性的动态.Net对象,无需更新您的类。(正如我所说,有时不是标准的) - Bishoy Hanna

50

一个很好的自动为您生成这些类的方法是将您的JSON输出复制并粘贴到这里:

http://json2csharp.com/

它将为您提供一个起点,以便您可以调整类进行反序列化。


6
另一种方法是在VisualStudio中使用“编辑>特殊粘贴>将JSON粘贴为类”。 - ShayD

32

我们可以很容易地使用字典和JavaScriptSerializer来解析JSON内容。以下是我从ashx文件解析JSON内容的示例代码。

var jss = new JavaScriptSerializer();
string json = new StreamReader(context.Request.InputStream).ReadToEnd();
Dictionary<string, string> sData = jss.Deserialize<Dictionary<string, string>>(json);
string _Name = sData["Name"].ToString();
string _Subject = sData["Subject"].ToString();
string _Email = sData["Email"].ToString();
string _Details = sData["Details"].ToString();

4
如果您没有时间或需要创建数据合同,那么这个解决方案非常有用。特别是如果您只对JSON结构中深埋的几个属性感兴趣,您可以使用一系列语句来导航到您需要的内容。请注意:要反序列化的类型也可能是以下之一:Dictionary<string,object>或ArrayList(当节点具有重复结构时)。 - Philippe Monnet
1
我在这里遇到了运行时异常:在反序列化代码的行中,类型“System.String”没有定义无参数构造函数。 - R.S.K

25

Newtonsoft.JSON 是这种情况下的好解决方案。相比其他解决方案,例如 JavaScriptSerializerDataContractJsonSerializerNewtonsoft.JSON 更快。

在本示例中,您可以看到以下内容:

var jsonData = JObject.Parse("your JSON data here");

然后你可以将jsonData转换为JArray,使用for循环在每次迭代时获取数据。
另外,我想补充一些内容:
for (int i = 0; (JArray)jsonData["data"].Count; i++)
{
    var data = jsonData[i - 1];
}

与动态对象一起使用并使用Newtonsoft序列化是一个不错的选择。

16

我同意Icarus的观点(如果可以评论,我也会评论), 但是我会使用一个Dictionary而不是一个CustomObject类(以防Facebook添加新功能)。

private class MyFacebookClass
{
    public IList<IDictionary<string, string>> data { get; set; }
}
或者
private class MyFacebookClass
{
    public IList<IDictionary<string, object>> data { get; set; }
}

3
在新版本中,使用动态(dynamic)效果更好。public IList<IDictionary<string, dynamic>> data { get; set; } - BJury

13

序列化:

// Convert an object to JSON string format
string jsonData = JsonConvert.SerializeObject(obj);

Response.Write(jsonData);

反序列化:

为了反序列化一个动态对象

  string json = @"{
      'Name': 'name',
      'Description': 'des'
    }";

var res = JsonConvert.DeserializeObject< dynamic>(json);

Response.Write(res.Name);

10
如果您正在使用 .NET Core 3.0,您可以使用内置的 System.Text.Json 来反序列化 JSON。
第一步是创建用于模拟 JSON 的类。有许多工具可以帮助完成此操作,其中一些答案在此处列出。
一些选项包括 http://json2csharp.comhttp://app.quicktype.io 或使用 Visual Studio(菜单 编辑特殊粘贴将 JSON 粘贴为类)。
public class Person
{
    public string Id { get; set; }
    public string Name { get; set; }
}

public class Response
{
    public List<Person> Data { get; set; }
}

然后您可以使用以下方式进行反序列化:
var people = JsonSerializer.Deserialize<Response>(json);

如果您需要添加设置,例如camelCase处理,则可以像这样将序列化器设置传递到反序列化器中:
var options = new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
var person = JsonSerializer.Deserialize<Response>(json, options);

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

1

这是另一个网站,只要您有正确格式的JSON字符串可用,它就可以帮助您获取所需的所有代码:

https://app.quicktype.io/


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