0

I'm consuming json from another party - I have no control over the format.

One property is poorly formatted in that it's an array of objects when there is more than one object but it's just an object when there's only one. Obviously, I'm getting an error when deserializing.

I'm assuming I'm going to have to write a custom converter to handle this. I'd prefer to have the serializing/deserializing of the underlying object(s) still handled by the default converter. Is that possible?

Here's an example of the json if only one "COMMENT":

{
  "COMMENT": {
    "@_SourceType": "MySource",
    "@_Type": "StatusCode",
    "@_Code": "11",
    "_Text": "THIS IS SOME TEXT"
  }
}

Here's an example if there's more than one:

{  
  "COMMENT": [
    {
      "@_SourceType": "MySource",
      "@_Type": "StatusCode",
      "@_Code": "11",
      "_Text": "THIS IS SOME TEXT"
    },
    {
      "@_SourceType": "MySource2",
      "@_Type": "StatusCode2",
      "@_Code": "12",
      "_Text": "THIS IS SOME MORE TEXT"
    }
  ]
}

I would like both to deserialize into a COMMENT array.

1 Answers1

0

So here's what I've tried that's giving me an error.

First, a trimmed down version of the class:

Public Class MyClass
    <JsonProperty(ItemConverterType:=GetType(CommentArrayJsonConverter))> Public Property Internal_Comment As Comment()
End Class

And here's the custom converter I'm trying to use:

Public Class CommentArrayJsonConverter
    Inherits JsonConverter

    Public Overrides Sub WriteJson(writer As JsonWriter, value As Object, serializer As JsonSerializer)

        If value Is Nothing Then
            Exit Sub
        End If

        Dim comments As Comment() = value

        If comments.Length = 1 Then
            serializer.Serialize(writer, comments.First)
        Else
            serializer.Serialize(writer, comments)
        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 = JsonToken.Null Then
            Return Nothing
        End If

        Dim comments() As Comment = Nothing
        If reader.TokenType = JsonToken.StartObject Then
            Dim jsonObject As JObject = JObject.Load(reader)

            Dim comment As New Comment
            serializer.Populate(jsonObject.CreateReader(), comment)

            comments = New Comment() {comment}
        Else
            Dim jsonArray As JArray = JArray.Load(reader)

            comments = jsonArray.ToObject(Of Comment())
        End If

        Return comments

    End Function
End Class

Am I right that the ReadJson function should return an array? Whether it comes in as a single object or an array, I want it to be deserialized into my object as an array. Walking through the function seems to do what I want, but after the method completes, json.net throws this error:

System.ArgumentException: 'The value "Comment[]" is not of type "Comment" and cannot be used in this generic collection.

It seems like it's expecting an object instead of the array, but the property is an array.