https://stackoverflow.com/questions/74027865/read-single-row-and-attributes-from-huge-json-file-via-jsontextreader

VbNet · Console

/Program.vb

Imports System
Imports System.Linq
Imports System.Collections
Imports System.Collections.Generic
Imports System.Data
Imports System.IO
Imports System.Globalization
Imports System.Reflection
Imports System.ComponentModel.DataAnnotations
Imports System.Xml.Linq
Imports System.Xml
Imports Microsoft.VisualBasic
Imports System.Text
Imports System.Text.RegularExpressions

Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq
Imports Newtonsoft.Json.Converters
Imports Newtonsoft.Json.Serialization

Imports NUnit.Framework

	' https://stackoverflow.com/questions/74027865/read-single-row-and-attributes-from-huge-json-file-via-jsontextreader

Public Module JsonExtensions
    Iterator Function DeserializeObjects(Of T)(ByVal stream As Stream, ByVal Optional settings As JsonSerializerSettings = Nothing) As IEnumerable(Of T)
		Using textReader = New StreamReader(stream, Encoding.UTF8, true, 1024, true)
			For Each item as T In DeserializeObjects(Of T)(textReader, settings)
				Yield item
			Next
        End Using
    End Function

	' Adapted from this answer https://stackoverflow.com/a/43747641/3744182
	' By https://stackoverflow.com/users/7912895/nocodename
	' To https://stackoverflow.com/questions/43747477/how-to-parse-huge-json-file-as-stream-in-json-net
    Iterator Function DeserializeObjects(Of T)(ByVal textReader As TextReader, ByVal Optional settings As JsonSerializerSettings = Nothing) As IEnumerable(Of T)
        Dim serializer = JsonSerializer.CreateDefault(settings)
        Using reader = New JsonTextReader(textReader) With { .CloseInput = False }
            While reader.Read()
                If reader.TokenType = JsonToken.StartObject Then
                    Yield serializer.Deserialize(Of T)(reader)
                End If
            End While
        End Using
    End Function

	Iterator Function DeserializeItemsByPath(Of T)(ByVal stream As Stream, regex as Regex, ByVal Optional settings As JsonSerializerSettings = Nothing) As IEnumerable(Of T)
		Using textReader = New StreamReader(stream, Encoding.UTF8, true, 1024, true)
			For Each item as T In DeserializeItemsByPath(Of T)(textReader, regex, settings)
				Yield item
			Next
        End Using
    End Function

	' Adapted from this answer https://stackoverflow.com/a/56411253/3744182
	' By https://stackoverflow.com/users/14357/spender
	' To https://stackoverflow.com/questions/43747477/how-to-parse-huge-json-file-as-stream-in-json-net
	Iterator Function DeserializeItemsByPath(Of T)(ByVal textReader As TextReader, ByVal regex as Regex, ByVal Optional settings As JsonSerializerSettings = Nothing) As IEnumerable(Of T)
        Dim serializer = JsonSerializer.CreateDefault(settings)
        Using reader = New JsonTextReader(textReader) With { .CloseInput = False }
            While reader.Read()
				If reader.TokenType <> JsonToken.PropertyName And regex.IsMatch(reader.Path)
                    Yield serializer.Deserialize(Of T)(reader)
                End If
            End While
        End Using
    End Function
End Module

Public Module TestClass	
	Friend Sub Test()
		Test1(GetJson())

		Console.WriteLine()
		Test2(GetJson())

		Console.WriteLine()
		Test3(JArray.Parse(GetJson())(0), 30000)
	End Sub

	Friend Sub Test1(ByVal json As String)
		Dim FileName = "Question74027865.json"
		File.WriteAllText(FileName, json)

		Using stream = File.OpenRead(FileName)
			Dim regex as Regex = new Regex("^\[[0-9]+\]\.facilities\.totalSize\.value$", RegexOptions.CultureInvariant Or RegexOptions.Compiled Or RegexOptions.Singleline)
			Console.WriteLine(regex)
			For Each value As Decimal in JsonExtensions.DeserializeItemsByPath(Of Decimal)(stream, regex)
				Console.WriteLine("totalSize: {0}", value)
			Next
		End Using

		File.Delete(FileName)
	End Sub	

	Friend Sub Test2(ByVal json As String)
		Dim FileName = "Question74027865.json"
		File.WriteAllText(FileName, json)

		Using stream = File.OpenRead(FileName)
			For Each jt As JObject in JsonExtensions.DeserializeObjects(Of JObject)(stream)
				Dim valueToken as JToken = jt.SelectToken("facilities.totalSize.value")
				If (valueToken IsNot Nothing)
					Console.WriteLine("totalSize: {0}", valueToken)
				End If
			Next
		End Using

		File.Delete(FileName)
	End Sub	

	Friend Sub Test3(Of T)(ByVal jObj as T, inCount as Integer)
		Dim FileName = "Question74027865.json"
		Using stream = File.OpenWrite(FileName)
			Using textWriter = new StreamWriter(stream)
				Using jsonWriter = new JsonTextWriter(textWriter)
					JsonSerializer.CreateDefault().Serialize(textWriter, Enumerable.Range(0, inCount).Select(Function(i) jObj))
				End Using
			End Using
		End Using

		Dim total as Decimal = 0D
		Dim count as Integer = 0

		Using stream = File.OpenRead(FileName)
			Dim regex as Regex = new Regex("^\[[0-9]+\]\.facilities\.totalSize\.value$", RegexOptions.CultureInvariant Or RegexOptions.Compiled Or RegexOptions.Singleline)
			Console.WriteLine(regex)
			For Each value As Decimal in JsonExtensions.DeserializeItemsByPath(Of Decimal)(stream, regex)
				total += value
				count += 1
			Next
		End Using

		Console.WriteLine("Grand total of {0} items: {1}.", count, total)
		
		File.Delete(FileName)
	End Sub	


	Function GetJson() as String
		Dim Jstring As String = <![CDATA[
[
  {
    "countryid": 1,
    "price": 2997,
    "facilities": {
      "totalSize": {
        "value": 80
      }
    }
  },
  {
    "countryid": 1,
    "price": 12997,
    "facilities": {
      "totalSize": {
        "value": 180
      }
    }
  },
  {
    "countryid": 1,
    "price": 10,
    "facilities": {
      "totalSize": {
      }
    }
  },
]
]]>.Value		
		Return Jstring		
	End Function
End Module

	Public Module Module1	
		Public Sub Main()
			Console.WriteLine("Environment version: " & Environment.Version.ToString())
			Console.WriteLine("Json.NET version: " & GetType(JsonSerializer).Assembly.FullName)
            Console.WriteLine("")

			Try

				TestClass.Test()

			Catch ex as Exception

				Console.WriteLine("Unhandled exception: ")
				Console.WriteLine(ex)
				Throw

			End Try
			
		End Sub	
	End Module

#If False Then
    <System.Runtime.CompilerServices.Extension()>
    Public Function ReadToContentAndAssert(ByVal reader As JsonReader) As JsonReader
        Return JsonExtensions.ReadAndAssert(reader).MoveToContentAndAssert()
    End Function

    <System.Runtime.CompilerServices.Extension()>
    Public Function MoveToContentAndAssert(ByVal reader As JsonReader) As JsonReader
        If reader Is Nothing Then Throw New ArgumentNullException()
        If reader.TokenType = JsonToken.None Then reader.ReadAndAssert()       ' Skip past beginning of stream.

        While reader.TokenType = JsonToken.Comment ' Skip past comments.
            reader.ReadAndAssert()
        End While

        Return reader
    End Function

    <System.Runtime.CompilerServices.Extension()>
    Public Function ReadAndAssert(ByVal reader As JsonReader) As JsonReader
        If reader Is Nothing Then Throw New ArgumentNullException()
        If Not reader.Read() Then Throw New JsonReaderException("Unexpected end of JSON stream.")
        Return reader
    End Function
#End If
;