1

I have am consuming some survey data via JSON from an API for my .Net app. I have created a class from the JSON file in my .net app. The JSON has a node called Response[] which is an array - so my survey platform gives me back multiple surveys. This works great when I get two or more surveys back (as its an array).

var root = JsonConvert.DeserializeObject<SurveyJsonModel.Rootobject>(json);

However, if the survey platform only returns back one survey the deserialisation fails, I suspect as the JSON is not returning an array. See attached screen shot of my model that I have created from the JSON. Any idea how I resolve - so it works for one record as well as multiples? Also not fail for zero records eithier. I suspect my model needs chnaging or do I need to use a different deserialisation method

TIAenter image description here

The error message I get is:

Please see below the error message:

Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'SurveyJsonModel+Response[]' because the type requires a JSON array(e.g. [1, 2, 3]) to deserialize correctly. To fix this error either change the JSON to a JSON array (e.g. [1, 2, 3]) or change the deserialized type so that it is a normal .NET type (e.g.not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.

This is my class that I am using - im not sure where I add the constructor

  public class SurveyJsonModel
{

    public class Rootobject
    {
        public Xml xml { get; set; }
        public Responses Responses { get; set; }
    }

    public class Xml
    {
        public string version { get; set; }
    }

    public class Responses
    {
        public Response[] Response { get; set; }
    }

    public class Response
    {
        public string startDate { get; set; }
        public string endDate { get; set; }
        public string status { get; set; }
        public string ipAddress { get; set; }
        
    }
}

This is my JSON string that returns one result,if it returns two surveys my code worked - but the below fails for one record as its not an array

{"?xml":{"@version":"1.0"},"Responses":{"Response":{"startDate":"2023-01-26 10:13:16","endDate":"2023-01-26 10:13:29","status":"0","ipAddress":"192.168.0.1"}}}

user13714356
  • 99
  • 1
  • 7
  • 2
    Please share the examples of json, error and the code (not as image) – Guru Stron Jan 26 '23 at 12:35
  • Does this answer your question? [Deserializing JSON when sometimes array and sometimes object](https://stackoverflow.com/questions/5224697/deserializing-json-when-sometimes-array-and-sometimes-object) – Palle Due Jan 26 '23 at 12:54
  • Opps sorry about that _ ihave added the error message above - hope this helps – user13714356 Jan 26 '23 at 13:04
  • We still don't have examples of the JSON, which is the most important bit. It would be *really* weird to change from an array to some other representation just because there's a single element. – Jon Skeet Jan 26 '23 at 16:47

2 Answers2

1

You don't need any custom converters, in this case I usually recommend to create a very simple JsonConstructor. And I fixed some bugs in your classes

using Newtonsoft.Json;

var result = JsonConvert.DeserializeObject<Rootobject>(json);

public partial class Responses
{
    public Response[] Response { get; set; }

    [JsonConstructor]
    public Responses(JToken Response)
    {
        if (Response.Type == JTokenType.Array)
            this.Response = Response.ToObject<Response[]>();
        else
            this.Response = new Response[] { Response.ToObject<Response>() };
    }
    public Responses() { }
}

public class Rootobject
{
    [JsonProperty("?xml")]
    public Xml Xml { get; set; }
    public Responses Responses { get; set; }
}
public class Xml
{
    [JsonProperty("@version")]
    public string Version { get; set; }
}
Serge
  • 40,935
  • 4
  • 18
  • 45
  • hi, thanks ever so much for the code - I have not used a constructor like this before. Do I add this to my Model .cs file. I have included what my class looks like above. Im not sure what JToken is - is this my json string that I am getting back from my API. Really appreciate all your help. – user13714356 Jan 26 '23 at 16:10
  • 1
    @user13714356 I updated my answer according to your new model. But your classes look very fany for me and I don't think that it will work. Can you post your json string pls, in order I could fix your model. – Serge Jan 26 '23 at 16:42
  • Yes sure -I have added teh JSON string above - this returns one survey response - which fails using my current method. Thanks ever so much - really appreciate it – user13714356 Jan 26 '23 at 16:50
  • 1
    @user13714356 I updated my answer according to a json string. It's tested and is working properly – Serge Jan 26 '23 at 17:16
  • You are an absolute star!!! Thats worked like magic - I really appreciate all your help. Absoultely amazing - have an wonderful Friday and weekend! – user13714356 Jan 27 '23 at 09:34
0

If you are using .NET Core 3 or higher you can try to change the type of the Response property to JsonElement and check the ValueKind property to see if it is an object or an array.

Joest
  • 158
  • 6