【问题标题】:parsing json w variable key-value pairs in c#在c#中解析json w变量键值对
【发布时间】:2017-07-21 21:30:22
【问题描述】:

我有以下内容

 [
   {    
     "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}
    ]
  }
]

【问题讨论】:

  • 您为什么要手动执行此操作,而不仅仅是使用专门为此目的设计的库,并且可能比您(或我)做得更好?
  • 我在其他 JSON 文件中使用 NewtonSoft,但这个格式很奇怪
  • 奇怪在哪里?
  • 我只是小心翼翼地修复了所有的缩进,甚至把你的伪代码变成了真正的代码——你为什么又把它搞砸了? (如果要加点东西,加到fixed版本...)
  • (不过,请您以后自己格式化帖子。)

标签: c# json io


【解决方案1】:

您绝对不应该手动解析它 - 只要您正确建模,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 中的内容 - 然后应该很容易将该表示转换为对其余代码更可口的表示。

【讨论】:

  • 非常感谢 :) 我想知道你是否知道我在哪里可以读到 (kvp => new { Date = kvp.Key, Price = kvp.Value }) 我使用表达式有时像这样,但希望我对到底发生了什么有更深入的了解
  • @DevinAndresSalemi:基本上找到一个好的 LINQ 教程。 (或者我的书,C# in Depth,当然:)
  • @jonskeet 你为什么这么说:“丑陋的,美国的”我真的很好奇。别担心我不是政治家,你也不是,所以我不会反对你;)但你必须有正当理由。
  • @CodingYoshi:就月/年/日而言,美国的日期格式很荒谬。它要么从小到大,要么从大到小。世界上大部分地区(日/月/年)使用的格式在不能自然排序方面绝对令人不快,并且不像其他数字表示(最左边=最重要的地方),但至少它去了在一个方向。对于像 JSON 这样的机器可读格式,ISO-8601 是 IMO 更好的选择。将年份放在首位使其明确 ISO-8601(因为没有人使用年-日-月)。
【解决方案2】:

您始终可以使用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");

【讨论】:

  • 除非根本不使用DailyClosePice(原文如此),而且您的字典中的值是string,而不是数字...
  • 我个人不会使用 DateTime 作为那里的键 - 最好直接进行解析,因为它采用非常特定的格式(可能不是默认区域性的格式)。我还建议不要使用 float 来表示货币价值。 (虽然它在 JSON 中是一个数值,但在许多平台上它可能已经被视为double...)
  • @JonSkeet Point 很好——尤其是关于日期解析。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多