如何用JsonTextReader读取大JSON中单个对象的多字段值?
处理大JSON文件的解决方案
问题核心
- 读取1.2GB级大型JSON,无需预定义实体类,支持
facilities.totalSize.value这类路径式访问嵌套值 - 现有代码触发“Object reference not set to an instance of an object”空引用错误
- 需要适配两类JSON结构:无包装的对象数组、带
listings/products等键名的嵌套数组 - 需求为逐个处理列表对象,读取指定多类型字段(如整数
countryid、字符串country、日期publishdate)
原代码错误原因
- 当
reader.TokenType = JsonToken.StartObject时,直接将reader.Value转为JToken是错误操作——此时reader.Value为空,正确做法是用JToken.Load(reader)加载整个对象,但加载后reader会自动移动到对象的EndToken位置,不能重复读取 - 未对
SelectToken的返回值做空值判断,一旦指定路径不存在就会触发空引用错误 - 未区分JSON根结构类型,遍历逻辑无法适配数组和带键对象两种场景
解决方案代码(VB.NET)
基于Newtonsoft.Json(Json.NET)实现流式处理,自动适配不同JSON结构:
Imports Newtonsoft.Json Imports Newtonsoft.Json.Linq ' 单个对象处理逻辑,可按需扩展字段读取规则 Sub ProcessSingleObject(obj As JObject) ' 读取嵌套路径值,先判空避免空引用 Dim totalSize = obj.SelectToken("facilities.totalSize.value") If totalSize IsNot Nothing Then Log($"jt totalSize: {totalSize.ToString()}") End If ' 多类型字段读取示例 Dim countryId = obj.SelectToken("countryid")?.Value(Of Integer)() Dim country = obj.SelectToken("country")?.Value(Of String)() Dim publishDate = obj.SelectToken("publishdate")?.Value(Of DateTime)() ' 此处添加自定义业务处理 If countryId IsNot Nothing Then Log($"Country ID: {countryId}") End If End Sub ' 大JSON读取主逻辑 Sub ReadLargeJson(url As String) Dim req As HttpWebRequest = CType(WebRequest.Create(url), HttpWebRequest) Using resp = req.GetResponse() Using stream = resp.GetResponseStream() Using reader = New JsonTextReader(New StreamReader(stream)) ' 先读取首个Token判断根结构 reader.Read() Select Case reader.TokenType Case JsonToken.StartArray ' 处理无包装的对象数组 While reader.Read() If reader.TokenType = JsonToken.StartObject Then Dim obj = JObject.Load(reader) ProcessSingleObject(obj) End If End While Case JsonToken.StartObject ' 处理带键的嵌套数组结构 Dim rootObj = JObject.Load(reader) ' 匹配常见数组键名,可根据实际场景扩展 Dim arrayToken As JToken = Nothing For Each key In {"listings", "products"} arrayToken = rootObj(key) If arrayToken?.Type = JTokenType.Array Then Exit For End If Next If arrayToken IsNot Nothing Then ' 逐个处理数组内的对象 For Each item In arrayToken.Children(Of JObject)() ProcessSingleObject(item) Next End If End Select End Using End Using End Using End Sub
关键优化点
- 流式处理:避免一次性加载1.2GB JSON到内存,仅加载单个对象完成处理后释放资源
- 空值安全:所有
SelectToken调用后通过?.做空值判断,彻底避免空引用错误 - 结构适配:自动识别根结构是数组还是带键对象,支持多种数组键名
- 类型安全:通过
Value(Of T)指定字段类型,确保类型转换准确
注意事项
- 需提前安装Newtonsoft.Json NuGet包,这是高效处理大JSON的核心依赖
- 若数组键名不确定,可遍历根对象所有属性,判断属性类型是否为数组
- 处理日期字段时,若JSON日期格式不符合.NET默认规则,可通过
JsonSerializerSettings指定自定义解析格式
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

