将对象从大型JSON文件转换为.NET中对象的最快方法

时间:2018-10-25 14:39:06

标签: c# .net json

我有一个任务,包括问题和带有对象的大型JSON文件。 JSON文件内部大约有500万个对象,并且具有303MB。

可以下载here这个大文件。

小预览里面的内容:

{ Reviewer:1, Movie:1535440, Grade:4, Date:'2005-08-18'}, 
{ Reviewer:1, Movie:1426604, Grade:4, Date:'2005-09-01'}, 
{ Reviewer:1, Movie:1815755, Grade:5, Date:'2004-07-20'}, 
{ Reviewer:2, Movie:2059652, Grade:4, Date:'2005-09-05'}, 
{ Reviewer:2, Movie:1666394, Grade:3, Date:'2005-04-19'}, 
{ Reviewer:2, Movie:1759415, Grade:4, Date:'2005-04-22'},

每一行代表一个评论。我们可以在此处找到评论者的ID,然后评分他用来评论电影的电影,电影ID和日期(以字符串形式)。

我需要将此文件导入到.NET Console应用程序中,反序列化并将其转换为对象,以便随后可以使用它们并创建一些方法,对象列表等。

问题示例:

  
      
  1. 使用参数N,来自评论者N的评论数是多少?
  2.   

(这应该是带有评论者ID参数的方法,一个评论者(人)可以对不同电影进行多次评论)

  
      
  1. 哪些评论者评论最多?
  2.   

问题是,每次我反序列化文件中的对象时,仅反序列化本身就需要10秒钟左右,而要求是,每种方法最多需要4秒钟的处理时间。 即使仅指定一个要从文件反序列化的字段,也要花费太多时间。

请问您知道一些有效的方法或某些nuGet软件包如何在不到4秒的时间内转换这些数据吗? 我只尝试了Newtonsoft.JSON。

我找到了一篇有趣的文章,但是我未能成功实现该代码,因为未完整描述代码片段,而且我无法弄清楚。这是该文章的link

我会很感谢每一个想法和帮助。

1 个答案:

答案 0 :(得分:3)

我决定尝试一下,因此我创建了一些代码,可以用来回答OP提出的两个示例问题。我能做的最好的就是在不到7秒的时间内得到结果,而不是OP要求的4:-(

解析审阅者ID

以下方法返回文件中的所有审阅者ID。我正在使用JsonTextReader仅提取Reviewer属性的值,而没有反序列化整个json对象:

private static IEnumerable<long> GetReviewerIds(string path)
{
    using (StreamReader streamReader = File.OpenText(path))
    using (JsonTextReader reader = new JsonTextReader(streamReader))
    {
        reader.CloseInput = true;

        while (reader.Read())
        {
            if (reader.TokenType == JsonToken.PropertyName && reader.Value.Equals("Reviewer"))
            {
                int? id = reader.ReadAsInt32();

                if (id.HasValue)
                {
                    yield return id.Value;
                }
            }
        }
    }
}

获取ID为4的评论者的评论数量

int reviewerId = 4;    
var stopWatch = Stopwatch.StartNew();

int numberOfReviews = GetReviewerIds(@"ratings.json").Count(x => x == reviewerId);

stopWatch.Stop();
Console.WriteLine($"Number of reviews: {numberOfReviews}; Execution time: {stopWatch.Elapsed:g}");

输出:

  

评论数:142;执行时间:0:00:06.2137702

获得前N名评论者

int numberOfReviewers = 3;
var stopWatch = Stopwatch.StartNew();

var reviewers = GetReviewerIds(@"ratings.json")
    .GroupBy(x => x)
    .Select(x => new
    {
        Id = x.Key,
        Count = x.Count()
    })
    .OrderByDescending(x => x.Count)
    .Take(numberOfReviewers)
    .ToList();

stopWatch.Stop();
Console.WriteLine($"Reviewer with ID {reviewers.First().Id} has done {reviewers.First().Count} reviews; Execution time: {stopWatch.Elapsed:g}");

输出:

  

ID 571的审阅者完成了154832条评论;执行时间:0:00:06.1256635