如何在C# .NET中反序列化复杂的JSON对象?

40

我有一个JSON字符串,需要一些帮助进行反序列化。

对我来说什么都没用……这是JSON:

{
    "response": [{
        "loopa": "81ED1A646S894309CA1746FD6B57E5BB46EC18D1FAff",
        "drupa": "D4492C3CCE7D6F839B2BASD2F08577F89A27B4ff",
        "images": [{
                "report": {
                    "nemo": "unknown"
                },
                "status": "rock",
                "id": "7e6ffe36e-8789e-4c235-87044-56378f08m30df",
                "market": 1
            },
            {
                "report": {
                    "nemo": "unknown"
                },
                "status": "rock",
                "id": "e50e99df3-59563-45673-afj79e-e3f47504sb55e2",
                "market": 1
            }
        ]
    }]
}

我有一个类的例子,但我不必使用那些类。我不介意使用其他类。

以下是这些类:

public class Report
{
    public string nemo { get; set; }
}

public class Image
{
    public Report report { get; set; }
    public string status { get; set; }
    public string id { get; set; }
    public int market { get; set; }
}

public class Response
{
    public string loopa { get; set; }
    public string drupa{ get; set; }
    public Image[] images { get; set; }
}

public class RootObject
{
    public Response[] response { get; set; }
}

我想提到我已经拥有Newtonsoft.Json,所以我可以使用其中的一些函数。

我该怎么做?


有没有抛出任何异常?错误信息是什么?你能贴出反序列化代码吗? - Rui Jarimba
我没有收到任何数据,也没有异常。在快速查看中出现了以下信息:“名称'不存在于当前上下文中”。 - Assaf Zigdon
1
查看答案并检查正确的答案以关闭此问题。 - filipko
12个回答

48
我在我的代码中使用了这样的方法,它运行得很好。
下面是你需要编写的一段代码。
using System.Web.Script.Serialization;

JavaScriptSerializer oJS = new JavaScriptSerializer();
RootObject oRootObject = new RootObject();
oRootObject = oJS.Deserialize<RootObject>(Your JSon String);

4
FYI:这是在System.Web.Extensions.dll中。 - jmbmage
1
我在哪里可以找到RootObject类?! - Mich
@Mich,RootObject类作为模型类的一部分在问题代码的结尾处提供。 - AntonioR
@Javal Patel - 很厉害的东西!“自动命名”映射可以节省很多映射代码的编写。感谢您的分享! - Spencer Sullivan

45

应该只需要这样:

var jobject = JsonConvert.DeserializeObject<RootObject>(jsonstring);

您可以将JSON字符串粘贴到此处:http://json2csharp.com/以检查您的类是否正确。


我尝试了这个,但是当进入快速查看时,我只得到了“名称'在当前上下文中不存在”的错误提示。 - Assaf Zigdon
你试过我链接的网站上的类吗?我看到它们与 RootObject 和 Response 类中使用的数组不同,而是使用了 List<T>。不确定这是否会有所不同。 - stevepkr84
是的,我改过它来进行测试,但原始代码来自这个网站。 - Assaf Zigdon

21
如果您使用的是 C# 2010 或更新版本,您可以使用动态类型(dynamic type)
dynamic json = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonstring);

然后,您可以使用点号表示法访问动态对象中的属性和数组:
string nemo = json.response[0].images[0].report.nemo;

本来可能是个好主意,但对我来说不起作用:编译动态表达式所需的一个或多个类型无法找到。您是否缺少引用? - Allen Linatoc

9

首先使用 NuGet Package Manager 安装 newtonsoft.json 包到 Visual Studio,然后添加以下代码:

ClassName ObjectName = JsonConvert.DeserializeObject < ClassName > (jsonObject);

但是这样能处理问题中的不规则JSON类型吗?你真的尝试过运行它吗? - Peter Mortensen

4

shareInfo是一个类:

public class ShareInfo
        {
            [JsonIgnore]
            public readonly DateTime Timestamp = DateTime.Now;
            [JsonProperty("sharename")]
            public string ShareName = null;
            [JsonProperty("readystate")]
            public string ReadyState = null;
            [JsonProperty("created")]
            [JsonConverter(typeof(Newtonsoft.Json.Converters.UnixDateTimeConverter))]
            public DateTime? CreatedUtc = null;
            [JsonProperty("title")]
            public string Title = null;
            [JsonProperty("getturl")]
            public string GettUrl = null;
            [JsonProperty("userid")]
            public string UserId = null;
            [JsonProperty("fullname")]
            public string Fullname = null;
            [JsonProperty("files")]
            public GettFile.FileInfo[] Files = new GettFile.FileInfo[0];
        }

// POST request.
            var gett = new WebClient { Encoding = Encoding.UTF8 };
            gett.Headers.Add("Content-Type", "application/json");
            byte[] request = Encoding.UTF8.GetBytes(jsonArgument.ToString());
            byte[] response = gett.UploadData(baseUri.Uri, request);

            // Response.
            var shareInfo = JsonConvert.DeserializeObject<ShareInfo>(Encoding.UTF8.GetString(response));

4

我有一个场景,这个代码帮助了我。

JObject objParserd = JObject.Parse(jsonString);

JObject arrayObject1 = (JObject)objParserd["d"];

D myOutput= JsonConvert.DeserializeObject<D>(arrayObject1.ToString());


3
 public static void Main(string[] args)
{
    string json = @" {
    ""children"": [
            {
        ""url"": ""foo.pdf"", 
                ""expanded"": false, 
                ""label"": ""E14288-Passive-40085-2014_09_26.pdf"", 
                ""last_modified"": ""2014-09-28T11:19:49.000Z"", 
                ""type"": 1, 
                ""size"": 60929
            }
        ]
     }";




    var result = JsonConvert.DeserializeObject<ChildrenRootObject>(json);
    DataTable tbl = DataTableFromObject(result.children);
}

public static DataTable DataTableFromObject<T>(IList<T> list)
{
    DataTable tbl = new DataTable();
    tbl.TableName = typeof(T).Name;

    var propertyInfos = typeof(T).GetProperties();
    List<string> columnNames = new List<string>();

    foreach (PropertyInfo propertyInfo in propertyInfos)
    {
        tbl.Columns.Add(propertyInfo.Name, propertyInfo.PropertyType);
        columnNames.Add(propertyInfo.Name);
    }

    foreach(var item in list)
    {
        DataRow row = tbl.NewRow();
        foreach (var name in columnNames)
        {
            row[name] = item.GetType().GetProperty(name).GetValue(item, null);
        }

        tbl.Rows.Add(row);
    }

    return tbl;
}

public class Child
{
    public string url { get; set; }
    public bool expanded { get; set; }
    public string label { get; set; }
    public DateTime last_modified { get; set; }
    public int type { get; set; }
    public int size { get; set; }
}

public class ChildrenRootObject
{
    public List<Child> children { get; set; }
}

1
虽然这段代码片段可能解决问题,但是【包括解释】(//meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) 真的有助于提高你的帖子质量。请记住您正在回答未来读者的问题,而那些人可能不知道您提出代码建议的原因。也请尽量不要在代码中添加过多的解释性注释,这会降低代码和解释的可读性! - kayess

2
我在使用C#解析和使用JSON对象时也遇到了问题。我尝试使用一些库来检查动态类型,但问题始终是如何检查属性是否存在。
最后,我偶然发现了这个网页,它为我节省了很多时间。它可以根据您的JSON数据自动创建一个强类型类,您将与Newtonsoft库一起使用,并且它完美地工作。它还适用于除C#以外的其他语言。

但是,那个代码能处理问题中特定的JSON中的不规则类型吗?你有试着运行过吗? - Peter Mortensen
它可以很好地处理缺少的JSON属性(当识别到对象数组中没有重复的属性时,会自动转换为可空类型)。当然,如果JSON完全不规则/随意,那么拥有C#转换器类是没有意义的。在这些情况下,使用dynamic是解决问题的方法。 在像我正在工作的项目这样的复杂情况下,我不得不进行一些小的手动调整,例如将一些整数类型转换为十进制类型(如果您提交的示例不包含小数),手动添加nullables等等。 - davidthegrey

1
您可以像下面这样一堆代码来解决您的问题。
public class Response
{
    public string loopa { get; set; }
    public string drupa{ get; set; }
    public Image[] images { get; set; }
}

public class RootObject<T>
    {
        public List<T> response{ get; set; }

    }

var des = (RootObject<Response>)Newtonsoft.Json.JsonConvert.DeserializeObject(Your JSon String, typeof(RootObject<Response>));

1
我正在使用以下内容:
    using System.Web.Script.Serialization;       

    ...

    public static T ParseResponse<T>(string data)
    {
        return new JavaScriptSerializer().Deserialize<T>(data);
    }

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