Imports System.Collections.Generic
Imports System.Globalization
Imports Newtonsoft.Json.Linq
Imports Newtonsoft.Json.Converters
Imports Newtonsoft.Json.Serialization
Public Module JsonExtensions
Private ReadOnly NumberTypes = New JTokenType() {JTokenType.[Integer], JTokenType.Float, JTokenType.[String], JTokenType.Comment, JTokenType.Raw, JTokenType.[Boolean]}
Private Function ValidateToken(o As JToken, validTypes As JTokenType(), nullable As Boolean) As Boolean
Return (Array.IndexOf(validTypes, o.Type) <> -1) OrElse (nullable AndAlso (o.Type = JTokenType.Null OrElse o.Type = JTokenType.Undefined))
<System.Runtime.CompilerServices.Extension> _
Public Function CanConvertToNullableLong(token As JToken) As Boolean
If token Is Nothing OrElse token.Type = JTokenType.Null OrElse token.Type = JTokenType.Boolean Then
If Not ValidateToken(token, NumberTypes, True) Then
Dim jValue = TryCast(token, JValue)
If jValue Is Nothing Then
If TypeOf jValue.Value Is BigInteger Then
Dim i = CType(jValue.Value, BigInteger)
Return i <= Long.MaxValue AndAlso i >= Long.MinValue
Dim s = CType(jValue, String)
Return Long.TryParse(s, NumberStyles.Number, NumberFormatInfo.InvariantInfo, v)
Public Sub TryConvertColumnsToNullableLong(root As JToken)
If TypeOf root Is JContainer Then
For Each group In DirectCast(root, JContainer) _
.OfType(Of JProperty)() _
.GroupBy(Function(p) p.Name) _
.Where(Function(g) g.All(Function(p) (p.Value.Type = JTokenType.String Or p.Value.Type = JTokenType.Null) AndAlso p.Value.CanConvertToNullableLong()))
p.Value = CType(p.Value, System.Nullable(Of Long))
Dim myRecords = "[{""PhoneNo"":""123456789"",""ID"":""46541"",""Name"":""John Doe"",""Email"":""hello@there""},{""PhoneNo"":""8675309"",""ID"":""1234"",""Name"":""Alice Bob"",""Email"":""goodbye@here""},{""PhoneNo"":null,""ID"":""0001"",""Name"":""No Phone"",""Email"":""no@email.either""}]"
Dim token = JToken.Parse(myRecords)
JsonExtensions.TryConvertColumnsToNullableLong(token)
Dim _dt = token.ToObject(Of DataTable)()
Console.WriteLine("Deserialized columns: ")
Console.WriteLine(JsonConvert.SerializeObject(_dt.Columns.Cast(Of DataColumn)().Select(Function(c) String.Format("{0}: {1}", c.ColumnName, c.DataType.FullName)), Newtonsoft.Json.Formatting.Indented))
Console.WriteLine("Deserialized and reserialized JSON: ")
Console.WriteLine(JsonConvert.SerializeObject(_dt, Newtonsoft.Json.Formatting.Indented))
Console.WriteLine("Json.NET version: " + GetType(JsonSerializer).Assembly.FullName)