使用Json.NET

时间:2017-03-20 08:45:32

标签: c# .net performance json.net

我正在尝试处理非常大量的数据(~1000个单独的文件,每个文件大约30 MB),以便用作机器学习算法的训练阶段的输入。使用JSON格式化的原始数据文件,我使用Json.NET的JsonSerializer类对它们进行反序列化。在程序结束时,Newtonsoft.Json.dll抛出 'OutOfMemoryException' 错误。有没有办法减少内存中的数据,或者我是否必须改变我的所有方法(例如切换到像Spark这样的大数据框架)来处理这个问题?

public static List<T> DeserializeJsonFiles<T>(string path)
{
    if (string.IsNullOrWhiteSpace(path))
        return null;

    var jsonObjects = new List<T>();
    //var sw = new Stopwatch();
    try
    {
        //sw.Start();
        foreach (var filename in Directory.GetFiles(path))
        {
            using (var streamReader = new StreamReader(filename))
            using (var jsonReader = new JsonTextReader(streamReader))
            {
                jsonReader.SupportMultipleContent = true;
                var serializer = new JsonSerializer();

                while (jsonReader.Read())
                {
                    if (jsonReader.TokenType != JsonToken.StartObject)
                        continue;

                    var jsonObject = serializer.Deserialize<dynamic>(jsonReader);

                    var reducedObject = ApplyFiltering(jsonObject) //return null if the filtering conditions are not met 
                    if (reducedObject == null)
                        continue;

                    jsonObject = reducedObject;
                    jsonObjects.Add(jsonObject);
                }
            }
        }    
        //sw.Stop();
        //Console.WriteLine($"Elapsed time: {sw.Elapsed}, Elapsed mili: {sw.ElapsedMilliseconds}");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error: {ex}")
        return null;
    }

    return jsonObjects;
}

感谢。

1 个答案:

答案 0 :(得分:2)

这对牛顿软件来说并不是一个问题。您正在将所有这些对象读入内存中的一个大列表中。它要求JsonSerializer创建另一个对象并且失败。

您需要从方法返回IEnumerable<T>,每个对象yield return,并在调用代码中处理它们,而不将它们存储在内存中。这意味着迭代IEnumerable<T>,处理每个项目,写入磁盘或任何他们需要的地方。