2017-07-21 23 views
1

我有以下解析JSONW¯¯可变键值对在C#

[ 
    {  
    "name": "ATVI", 
    "dailyClosePrice": [ 
     { 
     "3/15/2017": 210.08, 
     "4/6/2017": 235.08, 
     "4/21/2017": 243.61, 
     "2/16/2017": 205.43 
     } 
    ] 
    }, 
    { 
    "name": "ADBE", 
    "dailyClosePrice": [ 
     { 
     "3/15/2017": 241.96, 
     "4/6/2017": 270.22, 
     "4/21/2017": 281.22, 
     "2/16/2017": 225.26 
     } 
    ] 
    } 
] 

实际的文件比2更多的人,但你可以看到有两个 主要目的在这里。 我在分析键值对(例如"3/15/2017": 210.08)时遇到问题。

我需要一类离开这里,我想一个例子类将有

class Stock 
{ 
    public string Name{get;set;} 
    public List<Entry> Prices{get;set;} 
} 

class Entry 
{ 
    public string Date{get;set;} 
    public double Price{get;set;} 
} 

所以我想将文件解析成一个 列表

我想我可以使用一个StreamReader并使用Seek方法找到 一个“:”,但是我遇到的麻烦是如何才能够只读“ATVI”。例如,一旦我获得“ATVI”,我将该字符串设置为股票中的名称,然后可以搜索“{”并阅读“2017/3/15”,并将其设置为条目中的日期,然后寻找“ :“并在双读等。

如果我这样做,我不知道如何阅读流的选择元素,在C#中。在C#中,我主要阅读的是具有相同间距的字符串,通常我会使用C来处理更复杂的事情,但是我真的希望使用C#而不是C来完成此操作。

我不在乎我需要使用什么方法,我只是想在文件中读取。

如果我有类似下面,我只想用NewtonSoft

[ 
    { 
    "name": "ATVI", 
    "dailyClosePrice": [ 
     {"Date":"3/15/2017", "price":210.08}, 
     {"Date":"3/15/2017", "price": 210.08}, 
     {"Date":"4/6/2017", "price": 235.08}, 
     {"Date":"4/21/2017", "price": 243.61} 
    ] 
    }, 
    { 
    "name": "ADBE", 
    "dailyClosePrice": [ 
     {"Date":"3/15/2017", "price":210.08}, 
     {"Date":"3/15/2017", "price": 210.08}, 
     {"Date":"4/6/2017", "price": 235.08}, 
     {"Date":"4/21/2017", "price": 243.61} 
    ] 
    } 
] 
+1

你为什么要这样手动,而不是这样做只是使用专门为目的而设计的库,并有可能做它远远比你更好(或I)可以吗? – DavidG

+0

我使用NewtonSoft作为我的其他JSON文件,但是这个有一个奇怪的格式 –

+0

奇怪的是什么? – DavidG

回答

5

你绝对不应该由手工解析这个 - Json.NET将与这绝对精品,只要你模型,可以正确。 JSON表示一个对象列表,其中每个对象都有一个name(字符串)和一个dailyClosePrice,它似乎是一个总是有单个值的列表,而这个列表又是一个将对象映射到价格的日期。你可以代表相当容易:

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using Newtonsoft.Json; 

public class Stock 
{ 
    public string Name { get; set; } 
    public List<Dictionary<string, decimal>> DailyClosePrice { get; set; } 
} 

class Test 
{ 
    static void Main(string[] args) 
    { 
     string json = File.ReadAllText("test.json"); 
     var stocks = JsonConvert.DeserializeObject<List<Stock>>(json); 

     foreach (var stock in stocks) 
     { 
      Console.WriteLine($"Name: {stock.Name}"); 
      Console.WriteLine("Prices:"); 
      // Assume there's only ever a single entry, at least for now... 
      var prices = stock.DailyClosePrice.Single(); 
      // TODO: Parse the (ugly, US-based) date format... 
      var entries = prices.Select(kvp => new { Date = kvp.Key, Price = kvp.Value }); 
      foreach (var entry in entries) 
      { 
       Console.WriteLine($" {entry.Date}: {entry.Price}"); 
      } 
     } 
    } 
} 

现在Stock类是很丑陋,但它代表什么的JSON - 那么它应该是很容易的是表示转换成一个更可口之一其余的码。

+0

非常感谢:)我想知道你是否会发生知道我可以在哪里阅读(kvp => new {Date = kvp.Key,Price = kvp.Value})我有时会使用类似这样的表达式,但希望我更深入地了解 –

+0

@DevinAndresSalemi:基本上,找到一个很好的LINQ教程。 (或者我的书,C#深入,当然:) –

+0

@jonskeet你为什么这样说:“丑陋的,美国的”我真的很好奇。不要担心,我不是一个政治家,你也不会这样对你,但你必须有一个合理的理由。 – CodingYoshi

1

您始终可以使用this technique为您的JSON创建C#类。

您需要以下类的JSON:

public class Stock 
{ 
    public string Name { get; set; } 
    public IEnumerable<IDictionary<DateTime, float>> DailyClosePrice { get; set; } 
} 

下载JSON.NET库(它可以作为NuGet包)。然后,使用这样的库,和你做:

var stocks = JsonConvert.DeserializeObject<List<Stock>>("YourJSON"); 
+0

除了根本不使用'DailyClosePice'(sic),并且你的字典中的值是一个'字符串'而不是一个数字... –

+0

谢谢@JonSkeet。我编辑了答案。 – CodingYoshi

+0

我不会亲自使用'DateTime'作为那里的关键 - 鉴于它是以非常特定的格式(这可能不是默认的文化格式),所以最好直接进行解析。我也建议不要使用浮动货币值。 (虽然它是JSON中的一个数值,但在很多平台上已经可能被视为'double'了......) –