(NET) NET (2018)

Customize Newtonsoft.Json Serializer/Deserializer to convert Javascript Datetime and Number to .NET datatype.

Newtonsoft.Json Serializer/Deserializer is very useful and expandable library, I have a number of articles to processing: JSON

In this page I describe how to expand Newtonsoft.Json converter by own code. If you try to serialize .NET Type to JSON, you receive the similar representation of double (variabre with R suffix in VB.NET like Dim Price = 0.00000001R).



Usually this double-precision floating-point numbers will be not right handle in any server code, there for before deserialization this digit need to own deserializator:


 109:  Friend NotInheritable Class FormatNumbersAsTextConverter
 110:      Inherits JsonConverter
 111:   
 112:      Public Overrides ReadOnly Property CanRead As Boolean = False
 113:      Public Overrides ReadOnly Property CanWrite As Boolean = True
 114:   
 115:      ' <NullableAttribute(2)>
 116:      Public Overrides Sub WriteJson(writer As JsonWriter, value As Object, serializer As JsonSerializer)
 117:          writer.WriteValue(String.Format("{0:#######0.########}", value))
 118:      End Sub
 119:   
 120:      ' <NullableAttribute(2)>
 121:      Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object
 122:          Throw New NotImplementedException()
 123:      End Function
 124:   
 125:      Public Overrides Function CanConvert(objectType As Type) As Boolean
 126:          Return objectType Is GetType(Double)
 127:      End Function
 128:  End Class

To use this this serializer as


  32:      Public Shared Property DoubleNumericFormaterSerializerSettings = New JsonSerializerSettings With {.Converters = {New FormatNumbersAsTextConverter()}}
 ...   
 100:          Dim JsonString As String = JsonConvert.SerializeObject(InputJsonObject, DoubleNumericFormaterSerializerSettings)

you receive:





The second big problem to build interaction between Javascript and .NET is DateTime. In Javascript after serialization DateTime usually look as:


  19:                      "lastAccessed": 1574205139566

,

You can receive this data to ordinary model by one string of code, if you will specify special converter of this fields as Attribute:


 121:  Public Class TradeModel
 122:      Property id As Long
 123:      Property price As Double
 124:      Property qty As Double
 125:      Property quoteQty As Double
 126:      <Newtonsoft.Json.JsonConverter(GetType(JavascriptTimestampMicrosecondConverter))>
 127:      Property lastAccessed As DateTime
 128:      Property isBuyerMaker As Boolean
 129:      Property isBestMatch As Boolean
 130:  End Class

Then receiving JSON to model is possible by the ordinary way in one line of code:


 399:                          Dim TradesArr As JArray = JArray.Parse(Trades.Result)
 400:                          TradeList = JsonConvert.DeserializeObject(Of List(Of TradeModel))(TradesArr.ToString)

Also is use receive one converted variable (without attribute and model):


  33:      Public Shared Property JavascriptTimestampMicrosecondSerializerSettings = New JsonSerializerSettings With {.Converters = {New JavascriptTimestampMicrosecondConverter()}}
 360:      Dim ServerTime As DateTime = JsonConvert.DeserializeObject(Of DateTime)(ExchangeInfoJson("serverTime").ToString, JavascriptTimestampMicrosecondSerializerSettings)

This is my DateTime converter.


 131:  Public Class JavascriptTimestampMicrosecondConverter
 132:      Inherits JsonConverter
 133:   
 134:      Public Overrides ReadOnly Property CanRead As Boolean = True
 135:      Public Overrides ReadOnly Property CanWrite As Boolean = True
 136:   
 137:      Private Shared ReadOnly _epoch As DateTime = New DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)
 138:   
 139:      Public Overrides Sub WriteJson(writer As JsonWriter, value As Object, serializer As JsonSerializer)
 140:          writer.WriteRawValue((CType(value, DateTime) - _epoch).TotalMilliseconds)
 141:      End Sub
 142:   
 143:      Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object
 144:          If reader.Value Is Nothing Then
 145:              Return Nothing
 146:          Else
 147:              Return _epoch.AddMilliseconds(CLng(reader.Value)) 'double precizion float
 148:          End If
 149:      End Function
 150:   
 151:      Public Overrides Function CanConvert(objectType As Type) As Boolean
 152:          Return objectType Is GetType(DateTime)
 153:      End Function

Pay attention to variable CanRead/CanWrite. Unlike the previous converter, this converter is possible to use in opposite way too - rrom VB.NET DateTime to Javascript DateTime.




And this is another cool example to parse IPaddress in one case and custom error handling in other case. Usually I use my own ObjectDumper Reflection Object dumper., but this is not need, you always can use NewtonJson object serializer in this way.



   1:  Imports System.Runtime.CompilerServices
   2:  Imports Newtonsoft.Json
   3:   
   4:  Module Dumper
   5:      <Extension()>
   6:      Function ToPrettyString(ByVal value As Object) As String
   7:          Dim Setting As New JsonSerializerSettings With {
   8:              .ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
   9:              .[Error] = AddressOf SerializationErrorHanler
  10:          }
  11:          Setting.Converters.Add(New IPAddressConverter)
  12:          Setting.Converters.Add(New IPEndPointConverter)
  13:          Return JsonConvert.SerializeObject(value, Newtonsoft.Json.Formatting.Indented, Setting)
  14:      End Function
  15:   
  16:      Sub SerializationErrorHanler(Of T)(sender As Object, args As T)
  17:          Dim ErrorContext = TryCast(args, Newtonsoft.Json.Serialization.ErrorEventArgs).ErrorContext
  18:          Console.WriteLine(ErrorContext.Error.Message)
  19:          ErrorContext.Handled = True
  20:      End Sub
  21:   
  22:      <Extension()>
  23:      Function Dump(Of T)(ByVal value As T) As T
  24:          Console.WriteLine(value.ToPrettyString())
  25:          Return value
  26:      End Function
  27:  End Module

   1:  Imports Newtonsoft.Json
   2:  Imports Newtonsoft.Json.Linq
   3:  Imports System.Diagnostics.Eventing
   4:  Imports System.Net
   5:   
   6:  Class IPAddressConverter
   7:      Inherits JsonConverter
   8:      Public Overrides Function CanConvert(objectType As Type) As Boolean
   9:          Return (objectType = GetType(IPAddress))
  10:      End Function
  11:      Public Overrides Sub WriteJson(writer As JsonWriter, _value As Object, serializer As JsonSerializer)
  12:          writer.WriteValue(_value.ToString())
  13:      End Sub
  14:      Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object
  15:          Return IPAddress.Parse(CStr(reader.Value))
  16:      End Function
  17:  End Class
  18:   
  19:  Class IPEndPointConverter
  20:      Inherits JsonConverter
  21:      Public Overrides Function CanConvert(objectType As Type) As Boolean
  22:          Return (objectType = GetType(IPEndPoint))
  23:      End Function
  24:      Public Overrides Sub WriteJson(writer As JsonWriter, _value As Object, serializer As JsonSerializer)
  25:          Dim ep As IPEndPoint = CType(_value, IPEndPoint)
  26:          Dim jo As New JObject
  27:          jo.Add("Address", JToken.FromObject(ep.Address, serializer))
  28:          jo.Add("Port", ep.Port)
  29:          jo.WriteTo(writer)
  30:      End Sub
  31:      Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object
  32:          Dim jo As JObject = JObject.Load(reader)
  33:          Dim address1 As IPAddress = jo("Address").ToObject(Of IPAddress)(serializer)
  34:          Dim port1 As Integer = CInt(CLng(Fix(jo("Port"))) Mod Integer.MaxValue)
  35:          Return New IPEndPoint(address1, port1)
  36:      End Function
  37:  End Class


Comments ( )
<00>  <01>  <02>  <03>  <04>  <05>  <06>  <07>  <08>  <09>  <10>  <11>  <12>  <13>  <14>  <15>  <16>  <17>  <18>  <19>  <20>  <21>  <22>  <23
Link to this page: //www.vb-net.com/CustomizeJsonConverter/Index.htm
<SITEMAP>  <MVC>  <ASP>  <NET>  <DATA>  <KIOSK>  <FLEX>  <SQL>  <NOTES>  <LINUX>  <MONO>  <FREEWARE>  <DOCS>  <ENG>  <CHAT ME>  <ABOUT ME>  < THANKS ME>