使用LINQ解析唯一集合到JSON

本文关键字:集合 JSON 唯一 LINQ 使用 | 更新日期: 2023-09-27 18:16:19

我正在尝试使用LINQ解析JSON提要,并且无法将对象/值列表包装成合理的类。

我的JSON看起来像:

{
   "Project":[
      {
         "ID":"XY1212",
         "Name":"Some Name",
         "Description":"U.S. No 2 Diesel Retail Prices",
         "Manager":"Nora Sims",
         "Dept":"HR",
         "Updated":"2014-07-22",
         "Statistics":[
            [
               "20140722",
               32.22
            ],
            [
               "20140721",
               55
            ],
            [
               "20140720",
               343
            ],
            [
               "20140519",
               43
            ],
            [
               "20140421",
               3.971
            ],
            [
               "20140211",
               40.2
            ],
            [
               "20140210",
               17
            ],
            [
               "20140209",
               16
            ]
         ]
      }
   ]
}

从上面的JSON中,我有以下类结构:

public class Project
{
    public string ID { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public string Manager { get; set; }
    public string Dept { get; set; }
    public string Updated { get; set; }
    public List<List<object>> Statistics { get; set; }
}
public class RootObject
{
    public List<Project> Project { get; set; }
}
public class Statistic
{
    public Datetime ProjectDate { get; set; }
    public Decimal Sale { get; set; }
}

我试图解析的饲料,只是想要的"统计"数据,但不确定如何得到所有的值到"统计"的集合:

HttpClient() http = new HttpClient();
var json = await http.GetStringAsync(uri);
JObject jo = JObject.Parse(json);
var jList = from values in jo["Project"].Children()["Statistics"]
    select values;

当我通过以下循环检查jList时:

foreach (var stat in jList)
{
    Console.WriteLine(stat);
}

我可以"看到"所有的值,但它只循环一次,即jList只是一个大的[0],"值"是所有的[x, y], [x1, y1],…,即看起来像一个一维数组,其中包含许多二维数组。

我想循环遍历所有的"数组",我相信这就是它们的含义,在我在调试时在Visual Studio中看到的[0]内。

欢迎指教

使用LINQ解析唯一集合到JSON

您可以通过为您的Statistic类创建自定义JsonConverter来轻松解决这个问题。它将处理非常规的JSON,并允许您以您真正喜欢的方式定义项目类。

以下是转换器的代码:
class StatisticConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(Statistic));
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JArray array = JArray.Load(reader);
        return new Statistic
        {
            ProjectDate = DateTime.ParseExact(array[0].ToString(), "yyyyMMdd", 
                            System.Globalization.CultureInfo.InvariantCulture),
            Sale = array[1].ToObject<decimal>()
        };
    }
    public override bool CanWrite
    {
        get { return false; }
    }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

要使用转换器,我们只需要对你的类做一些小的改变。首先,将Statistics属性更改为List<Statistic>而不是List<List<object>>。(不要担心它与JSON不匹配——这就是转换器的作用。)

public class Project
{
    public string ID { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public string Manager { get; set; }
    public string Dept { get; set; }
    public string Updated { get; set; }
    public List<Statistic> Statistics { get; set; }
}

接下来用[JsonConverter]属性装饰Statistic类,将其绑定到自定义转换器:

[JsonConverter(typeof(StatisticConverter))]
public class Statistic
{
    public DateTime ProjectDate { get; set; }
    public Decimal Sale { get; set; }
}

就是这样!现在,您可以按正常方式反序列化,并且您将获得您想要的统计数据列表。

RootObject root = JsonConvert.DeserializeObject<RootObject>(json);

问题不在于您的代码,而在于从HttpClient返回的JSON字符串。因为它有没有键的部分,所以很难排序,而且statistic的每个子函数都是那个子函数的子函数(如果我的眼睛没有欺骗我的话)。

但是,使用下面的代码,我能够读取Statistics值。

JObject jo = JObject.Parse(json);
            var jList = from values in jo["Project"]
                        select values;
            foreach (var j in jList)
            {
                var l = j["Statistics"].Children();
                foreach (var m in l.Children())
                {
                    string a = m.ToString();
                }
            }

在第一个循环中,m有Date,在第二个循环中,它有sale。因为没有键,所以我不知道有什么其他的方法来引用它们。

代码少一点,但结果相似

JObject jo = JObject.Parse(json);
        for (int i = 0; i < jo.Count; i++)
        {
            var jList = from values in jo["Project"][i]["Statistics"]
                        select values;                
            foreach (var stat in jList)
            {
                //here stat looks like {["20140722", 32.22]}
            }
        }