VbNet · Console
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