【问题标题】:Cannot deserialize JSON array into type无法将 JSON 数组反序列化为类型
【发布时间】:2012-02-21 18:19:24
【问题描述】:

我正在使用 Newtonsoft JSON.NET 包来反序列化我的响应。这是从 Omniture 拉回可用指标的调用的示例响应。

[
{"rsid":"somersid",
 "site_title":"somesitetitle",
 "available_metrics":[
    {"metric_name":"averagepagedepth","display_name":"Average Page Depth"},
    {"metric_name":"averagetimespentonpage","display_name":"Average Time Spent on Page"},
    {"metric_name":"averagetimespentonsite","display_name":"Average Time Spent on Site"},
    {"metric_name":"averagevisitdepth","display_name":"Average Visit Depth"},
    {"metric_name":"customersdaily","display_name":"Daily Unique Customers"},
    {"metric_name":"customersloyal","display_name":"Loyal Customers"},
    {"metric_name":"customersmonthly","display_name":"Monthly Unique Customers"},
    {"metric_name":"customersnew","display_name":"New Customers"},
    {"metric_name":"customersquarterly","display_name":"Quarterly Unique Customers"}
    ]
 }
]

对于我想反序列化的类,我首先尝试了 svcutil 针对其架构生成的类。它正确创建了类,并且在反序列化简单对象时它们似乎可以工作。但是任何带有嵌套数组(如上)的东西都因“无法将 JSON 数组反序列化为类型”错误而失败。经过仔细检查,svcutil 生成的类使用如下数组:

public partial class report_suite_metrics {
    public string rsid { get; set;} ;
    public string site_title { get; set;} ;
    public metric[] available_metrics { get; set;} ;
}

public partial class metric {
    public string metric_name {get; set;}
    public string display_name {get; set;}
}

也许 JSON.NET 正试图将该数组强制为我认为的通用列表。我看到的所有 JSON.NET 示例都使用 List 来处理子数组,所以我创建了新的类来使用 json2csharp 实用程序 (http://json2csharp.com/) 进行测试并得到了这个:

public class AvailableMetric {
    public string metric_name { get; set; }
    public string display_name { get; set; }
}

public class RootObject {
    public string rsid { get; set; }
    public string site_title { get; set; }
    public List<AvailableMetric> available_metrics { get; set; }
}

看起来与所有 JSON.NET 示例完全一致。但它抛出了完全相同的错误:(什么给出?有人遇到过这种问题吗?这似乎是一个非常简单和常见的情况,所以我很惊讶它没有按预期工作。谢谢

【问题讨论】:

  • 您在返回的单个项目周围有方括号;你是在反序列化为report_suite_metrics[] 还是report_suite_metrics?前者应该可以工作,后者会给你你看到的错误。
  • @meklarian 我不敢相信我错过了,这正是导致问题的原因,感谢您给了我第二眼!请继续发表您的评论作为答案,这样我就可以给予您信任,再次感谢!

标签: c# json serialization json.net


【解决方案1】:

你给出的两组类型都有效;问题是返回的源数据是核心类型的数组,而不是单个实例。请注意您在整个数据单元周围提供的 JSON 示例中的方括号。

这是一个测试控制台应用程序,您可以使用它来检查您看到的 JSON。

要使用它,请将上面提供的 JSON 复制到任意文本文件中,然后从应用程序中打开它。

请注意,反序列化为数组可以正常工作,但单个元素(根据您的期望)会失败。

如果您创建一个包含相同示例数据但没有外部 [ ] 括号的示例文本文件,您将看到数组反序列化失败并且单个元素有效。

using System.Windows.Forms;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace RptSuiteMetricsTest1
{
    class Program
    {
        public class report_suite_metrics
        {
            public string rsid { get; set; }
            public string site_title { get; set; }
            public metric[] available_metrics { get; set; }
        }

        public class metric
        {
            public string metric_name { get; set; }
            public string display_name { get; set; }
        }

        public class AvailableMetric
        {
            public string metric_name { get; set; }
            public string display_name { get; set; }
        }

        public class RootObject
        {
            public string rsid { get; set; }
            public string site_title { get; set; }
            public List<AvailableMetric> available_metrics { get; set; }
        }

        [STAThread]
        static void Main(string[] args)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            DialogResult dr = dlg.ShowDialog();
            if (dr != DialogResult.OK) { return; }

            // NOTE: ...or replace this with a string containing the json data to test.
            string jsonData = System.IO.File.ReadAllText(dlg.FileName);

            Console.WriteLine("Deserialize as array");
            try
            {
                report_suite_metrics[] dataset = JsonConvert.DeserializeObject<report_suite_metrics[]>(jsonData);
                Console.WriteLine("{0} items found.", dataset.Length);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception of type {0}", ex.GetType().Name);
            }

            Console.WriteLine("Deserialize as array, alternate type");
            try
            {
                RootObject[] dataset = JsonConvert.DeserializeObject<RootObject[]>(jsonData);
                Console.WriteLine("{0} items found.", dataset.Length);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception of type {0}", ex.GetType().Name);
            }

            Console.WriteLine();

            Console.WriteLine("Deserialize as single item");
            try
            {
                report_suite_metrics dataset = JsonConvert.DeserializeObject<report_suite_metrics>(jsonData);
                Console.WriteLine("rsid=\"{0}\"", dataset.rsid);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception of type {0}", ex.GetType().Name);
            }

            Console.WriteLine("Deserialize as single item, alternate type");
            try
            {
                RootObject dataset = JsonConvert.DeserializeObject<RootObject>(jsonData);
                Console.WriteLine("rsid=\"{0}\"", dataset.rsid);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception of type {0}", ex.GetType().Name);
            }

            Console.ReadKey();
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-16
    • 1970-01-01
    • 2016-04-06
    • 1970-01-01
    • 1970-01-01
    • 2019-03-18
    • 1970-01-01
    • 2013-07-19
    相关资源
    最近更新 更多