使用LINQ to JSON解析唯一集合

时间:2014-08-05 04:00:30

标签: c# json linq json.net

我正在尝试使用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; }
}

我正在尝试解析Feed并只想要“统计”数据,但不知道如何将所有值都放入“统计”集合中:

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],...的值都是。 ..,即看起来像一个维度的数组,里面有许多2D数组。

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

任何建议表示赞赏。

2 个答案:

答案 0 :(得分:2)

您可以通过为JsonConverter课程制作自定义Statistic来轻松解决此问题。它将处理非常规JSON,并允许您以您真正喜欢的方式定义Project类。

以下是转换器的代码:

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; }
}

接下来使用Statistic属性装饰您的[JsonConverter]课程,将其与自定义转换器绑定:

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

那就是它!现在您可以正常反序列化,并且您可以按照自己的方式获得统计信息列表。

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

Working demo here

答案 1 :(得分:0)

问题不在于您的代码,因为它是从HttpClient返回的JSON字符串。 因为它的部分没有钥匙,所以很难排序,每个统计的孩子都是那个孩子的孩子(如果我的眼睛不欺骗我)。

但是,使用下面的代码,我可以单独阅读统计数据值

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,在第二个循环中它具有销售。因为这些没有关键,我不知道任何其他方式来引用它们。

代码少但结果相似

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]}
            }

        }