无法将JSON数组反序列化为类型
本文关键字:反序列化 类型 数组 JSON | 更新日期: 2023-09-27 18:25:15
我正在使用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正试图将该数组强制转换为我认为的泛型List。我看到的所有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示例完全一致。但它抛出了完全相同的错误:(发生了什么?有人遇到这种问题吗?这似乎是一个非常简单和常见的情况,所以我很惊讶它没有像预期的那样工作。谢谢
您给定的两组类型都工作;问题是返回的源数据是核心类型的数组,而不是单个实例。请注意您提供的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();
}
}
}