使用C#反序列化JSON


206

我正在尝试将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
写一个专门的自定义解串器来满足这样的json ...
ashutosh raina 2011年

2
或者,您可以使用一个Dictionary<string,string>,签出:stackoverflow.com/questions/7699972/…–
卡卡西

9
您的朋友:json2csharp.com
nawfal

4
实际上,视觉工作室(截至2013年或2012年,已安装Web工具)内置了以下确切功能:编辑>选择性粘贴> JSON作为类粘贴JSON
floomby

Answers:


264

您需要创建这样的结构:

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字符串化。谢谢。

@Kevin Holditch感谢您的纠正。我错过了重要的一点:)
Icarus

2
我对System.Web.Script.Serialization.JavaScriptSerializer()的不满意之处在于,您总是需要定义的类型T。在Java中,有一个org.java库(包)仍然是匿名的:“ JSONObject [” param“]。JSONarray(5)”等
体育

2
重要的是要注意,id和name属性的设置器必须公开。如果将它们设置为私有或受保护,则反序列化将执行而不会出错,但是所有数据将为null。
艾萨克·扎伊斯

2
@sports,可以在C#中通过反序列化为动态来实现,但是如果反序列化为已知类型则性能会更好。
PRMan

50

有时我更喜欢动态对象:

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

2
一个解释将是有条理的。
彼得·莫滕森

与@Icarus接受的答案相比,您为什么更喜欢它?
质疑

@问题,反序列化为强类型类将忽略类中没有的任何属性,而反序列化为动态对象将仅返回动态.Net对象,该对象可灵活地适应将来创建的任何新属性,而无需更新您的类。(如我所说,有时不是标准的)
比绍伊·汉娜


28

我们可以很容易地借助Dictionary和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();

3
如果您没有时间或不需要创建数据合同,则此解决方案非常有用。特别是如果您只对JSON结构中深处的一些属性感兴趣的话。在这种情况下,您可以使用一系列语句导航到所需的内容。注意:要反序列化的类型也可能是以下之一:Dictionary <string,object>或ArrayList(当节点具有重复结构时)。
菲利普·莫奈

1
我收到一个运行时异常,它是:在反序列化代码行上没有为'System.String'类型定义无参数构造函数。
RSK

20

Newtonsoft.JSON在这种情况下是一个很好的解决方案。也Newtonsof.JSON就是比别人快等JavaScriptSerializerDataContractJsonSerializer

在此示例中,您可以执行以下操作:

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序列化是一个不错的选择。


15

我同意Icarus(如果可以的话会发表评论),但是我将使用Dictionary(以防Facebook添加某些东西)而不是使用CustomObject类。

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

要么

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

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

3

序列化:

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

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

如果使用的是.NET Core 3.0,则可以使用System.Text.Json(现已内置)来反序列化JSON。

第一步是创建用于对JSON建模的类。有许多工具可以帮助解决此问题,此处列出了一些答案。

某些选项是http : //json2csharp.com,http : //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);
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.