What you can do is to create a JsonConverter
that serializes your Actor
class as an IEnumerable<object>
in the correct order, then in deserialization reads the JSON using LINQ to JSON, checks that the token read is an array, then sets the properties in the equivalent order.
You could hardcode this for your Actor
class, but I think it's more interesting to create a generic converter that converts non-enumerable POCO from and to a JSON array using the POCO type's property order. This order can be specified in your class using the <JsonProperty(Order := NNN)>
attribute.
Thus, 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 fiddle.
Note an updated c# version that handles JsonConverter
attributes applied to properties can be found here.