JSON deserialization in Visual Basic.NET

I wonder if you can help me create a VB.Net class into which I can deserialize the following JSON response:

{ "id":86, "name":"Tom", "likes": { "actors":[ ["Clooney",2,30,4], ["Hanks",104,15,1] ] }, "code":8 } 

I have the following:

 Class mLikes Public actors As IList(Of IList(Of String)) end Class 

and

 Class Player <JsonProperty(PropertyName:="id")> Public Id As Integer <JsonProperty(PropertyName:="name")> Public Name As String <JsonProperty(PropertyName:="likes")> Public Likes As mLikes <JsonProperty(PropertyName:="code")> Public Code As Integer End Class 

I use Newtonsoft.Json to deserialize:

 Result = Newtonsoft.Json.JsonConvert.DeserializeObject(Of Player)(jsonResponse) 

If I know that actors' elements always follow the same format -

 Class Actor Public Name as String Public NumberOfMovies as Integer Public NumberOfAwards as Integer Public NumberOfTVshows as Integer End Class 

Is there a way I can parse the JSON response so that Player.Likes.Actors is List (Of Actor) instead of List (Of List (Of String)), which I have now?

+1
source share
1 answer

What you can do is create a JsonConverter that serializes your Actor class as IEnumerable<object> in the correct order, then when deserializing it reads JSON using LINQ to JSON , checks that the token being read is an array, then sets the properties in an equivalent order.

You can hardcode this for your Actor class, but I think it’s more interesting to create a universal converter that converts the non-enumerable POCO from and into the JSON array using an order of properties of the POCO type. This order can be specified in your class using <JsonProperty(Order := NNN)> .

So, the converter:

 Public Class ObjectToArrayConverter(Of T) Inherits JsonConverter Public Overrides Function CanConvert(objectType As Type) As Boolean Return GetType(T) = objectType End Function Private Shared Function ShouldSkip(p As JsonProperty) As Boolean Return p.Ignored Or Not p.Readable Or Not p.Writable End Function Public Overrides Sub WriteJson(writer As JsonWriter, value As Object, serializer As JsonSerializer) If value Is Nothing Then writer.WriteNull() Else Dim type = value.GetType() Dim contract = TryCast(serializer.ContractResolver.ResolveContract(type), JsonObjectContract) If contract Is Nothing Then Throw New JsonSerializationException("invalid type " & type.FullName) End If Dim list = contract.Properties.Where(Function(p) Not ShouldSkip(p)).Select(Function(p) p.ValueProvider.GetValue(value)) serializer.Serialize(writer, list) End If End Sub Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object If reader.TokenType = JTokenType.Null Then Return Nothing End If Dim token = JArray.Load(reader) Dim contract = TryCast(serializer.ContractResolver.ResolveContract(objectType), JsonObjectContract) If contract Is Nothing Then Throw New JsonSerializationException("invalid type " & objectType.FullName) End If Dim value = If(existingValue, contract.DefaultCreator()()) For Each pair In contract.Properties.Where(Function(p) Not ShouldSkip(p)).Zip(token, Function(p, v) New With { Key.Value = v, Key.Property = p }) Dim propertyValue = pair.Value.ToObject(pair.Property.PropertyType, serializer) pair.Property.ValueProvider.SetValue(value, propertyValue) Next Return value End Function End Class 

And your class:

 <JsonConverter(GetType(ObjectToArrayConverter(Of Actor)))> _ Public Class Actor ' Use [JsonProperty(Order=x)] //http://www.newtonsoft.com/json/help/html/JsonPropertyOrder.htm to explicitly set the order of properties <JsonProperty(Order := 0)> _ Public Property Name As String <JsonProperty(Order := 1)> _ Public Property NumberOfMovies As Integer <JsonProperty(Order := 2)> _ Public Property NumberOfAwards As Integer <JsonProperty(Order := 3)> _ Public Property NumberOfTVshows As Integer End Class 

Working violin .

Note that an updated version of C # that handles JsonConverter attributes applied to properties can be found here .

0
source

Source: https://habr.com/ru/post/1260232/


All Articles