【发布时间】:2019-07-01 22:26:10
【问题描述】:
使用 JSON.NET,我正在从一个大文件中读取数组中的 JSON 对象。 在读取 JSON 对象时,它会被有条件地转换为目标类,并作为 IEnumerable 中的项目返回。
我使用 IEnumerable 允许我从文件中“拉”出对象并在读取它们时对其进行处理,从而避免将所有对象读入内存。
从 CSV 文件中读取行时,我使用了类似的技术,我使用 CsvHelper ShouldSkipRecord() 有条件地处理 CSV 文件中的行。
我还没有找到一种方法来过滤从数组中读取的 JSON 对象,我最终使用 LINQ Where 在对象被转换并添加到 IEnumerable 之前对其进行过滤。问题是 Where 子句将所有对象读入内存,违背了使用 IEnumerable 的目的。
我知道我可以手动读取每个对象,然后处理它们,但我正在寻找一种更优雅的方式来获得一种回调形式,允许我提取记录和我不想要的回调过滤记录。
例如我如何过滤 CSV 文件中的行:
internal static bool ShouldSkipRecord(string[] fields)
{
// Skip rows with incomplete data
// 2019-01-24 20:46:57 UTC,63165,4.43,6.23,6.80,189,-18,81.00,16.00,6.23
// 2019 - 01 - 24 20:47:40 UTC,63166,4.93,5.73,5.73,0,-20,,,5.73
if (fields.Length < 10)
return true;
// Temperature and humidity is optional, air quality is required
if (string.IsNullOrEmpty(fields[9]))
return true;
return false;
}
例如我如何过滤 JSON 对象:
internal static PurpleAirData Convert(Feed jsonData)
{
PurpleAirData data = new PurpleAirData()
{
TimeStamp = jsonData.CreatedAt.DateTime,
AirQuality = Double.Parse(jsonData.Field8)
};
// Temperature and humidity is optional
if (double.TryParse(jsonData.Field6, out double val))
data.Temperature = val;
if (double.TryParse(jsonData.Field7, out val))
data.Humidity = val;
return data;
}
internal static IEnumerable<PurpleAirData> Load(JsonTextReader jsonReader)
{
// Deserialize objects in parts
jsonReader.SupportMultipleContent = true;
JsonSerializer serializer = new JsonSerializer();
// Read Channel
// TODO : Add format checking
jsonReader.Read();
jsonReader.Read();
jsonReader.Read();
Channel channel = serializer.Deserialize<Channel>(jsonReader);
// Read the Feeds
jsonReader.Read();
jsonReader.Read();
// TODO : The Where results in a full in-memory iteration defeating the purpose of the streaming iteration
return serializer.Deserialize<List<Feed>>(jsonReader).Where(feed => !string.IsNullOrEmpty(feed.Field8)).Select(Convert);
}
示例 JSON:
{
"channel":{
"id":622370,
"name":"AirMonitor_e81a",
"latitude":"0.0",
"longitude":"0.0",
"field1":"PM1.0 (ATM)",
"field2":"PM2.5 (ATM)",
"field3":"PM10.0 (ATM)",
"field4":"Uptime",
"field5":"RSSI",
"field6":"Temperature",
"field7":"Humidity",
"field8":"PM2.5 (CF=1)",
"created_at":"2018-11-09T00:35:34Z",
"updated_at":"2018-11-09T00:35:35Z",
"last_entry_id":65435
},
"feeds":[
{
"created_at":"2019-01-10T23:56:09Z",
"entry_id":56401,
"field1":"1.00",
"field2":"1.80",
"field3":"1.80",
"field4":"369",
"field5":"-30",
"field6":"66.00",
"field7":"59.00",
"field8":"1.80"
},
{
"created_at":"2019-01-10T23:57:29Z",
"entry_id":56402,
"field1":"1.08",
"field2":"2.44",
"field3":"3.33",
"field4":"371",
"field5":"-32",
"field6":"66.00",
"field7":"59.00",
"field8":"2.44"
},
{
"created_at":"2019-01-26T00:14:04Z",
"entry_id":64400,
"field1":"0.27",
"field2":"0.95",
"field3":"1.25",
"field4":"213",
"field5":"-27",
"field6":"72.00",
"field7":"40.00",
"field8":"0.95"
}
]
}
示例 JSON:
[
{
"monthlyrainin": 0.01,
"humidityin": 42,
"eventrainin": 0,
"humidity": 29,
"maxdailygust": 20.13,
"dateutc": 1549476900000,
"battout": "1",
"lastRain": "2019-02-05T19:21:00.000Z",
"dailyrainin": 0,
"tempf": 52.2,
"winddir": 286,
"totalrainin": 0.01,
"dewPoint": 20.92,
"baromabsin": 29.95,
"hourlyrainin": 0,
"feelsLike": 52.2,
"yearlyrainin": 0.01,
"uv": 1,
"weeklyrainin": 0.01,
"solarradiation": 157.72,
"windspeedmph": 0,
"tempinf": 73.8,
"windgustmph": 0,
"battin": "1",
"baromrelin": 30.12,
"date": "2019-02-06T18:15:00.000Z"
},
{
"dewPoint": 20.92,
"tempf": 52.2,
"maxdailygust": 20.13,
"humidityin": 42,
"windspeedmph": 4.03,
"eventrainin": 0,
"tempinf": 73.6,
"feelsLike": 52.2,
"dateutc": 1549476600000,
"windgustmph": 4.92,
"hourlyrainin": 0,
"monthlyrainin": 0.01,
"battin": "1",
"humidity": 29,
"totalrainin": 0.01,
"baromrelin": 30.12,
"winddir": 314,
"lastRain": "2019-02-05T19:21:00.000Z",
"yearlyrainin": 0.01,
"baromabsin": 29.94,
"dailyrainin": 0,
"battout": "1",
"uv": 1,
"solarradiation": 151.86,
"weeklyrainin": 0.01,
"date": "2019-02-06T18:10:00.000Z"
}]
JSON.NET 中有没有一种方法可以在读取对象时对其进行过滤?
【问题讨论】:
-
你的 JSON 文件格式是什么样的?
-
您可能会从 Issues parsing a 1GB json file using JSON.NET 和 Deserialize json array stream one item at a time 开始,但不知道您的文件格式很难确定。
-
我添加了一些示例 JSON sn-ps。