BaltoStar
BaltoStar

Reputation: 8997

JSON deserialize to List<T>

I have an ASP.NET Web API GET endpoint

public class MyType
{
  public bool Active { get; set; }
  public DateTime CreateDate { get; set; }
  public int Id { get; set; }
  public string Description { get; set; }
}

public class MyResponse
{
  public List<MyType> Results { get; set; }
}

[HttpGet]
public MyResponse GetResults()

For the case where Results contains 2 items , the json return string is

{"Results":[{"Active":true,"CreateDate":"2014-01-01T00:00:00","Id":1,"Description":"item 1 description"},{"Active":true,"CreateDate":"2014-01-01T00:00:00","Id":2,"Description":"item 2 description"}]}

On the client side I wish to deserialize the json to List<MyType>

( being a bit loose with the language in the name of brevity )

List<MyType> results = HttpResponseMessage.Content.ReadAsAsync<List<MyType>>(new [] { new JsonMediaTypeFormatter () }).Result;

but this throws exception

Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[MyType]' 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<T>) 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.

   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType)
   at System.Net.Http.Formatting.JsonMediaTypeFormatter.<>c__DisplayClass8.<ReadFromStreamAsync>b__6()
   at System.Threading.Tasks.TaskHelpers.RunSynchronously[TResult](Func`1 func, CancellationToken cancellationToken)

Upvotes: 0

Views: 1972

Answers (2)

BateTech
BateTech

Reputation: 6526

The MyResponse class is what is getting serialized to JSON, so that is the type that should be used when calling the ReadAsAsync method.

MyResponse responseContent = HttpResponseMessage.Content.ReadAsAsync<MyResponse>(new [] { new JsonMediaTypeFormatter () });

Then if you want to access the list of results, then use responseContent.Results

From the examples I've seen, you can also omit the IEnumerable<MediaTypeFormatter> parameter, so this might work as well. http://msdn.microsoft.com/en-us/library/hh944541(v=vs.118).aspx

MyResponse responseContent = HttpResponseMessage.Content.ReadAsAsync<MyResponse>();

Upvotes: 0

rfernandes
rfernandes

Reputation: 1161

Your Web API method returns an object, and not a list - and you are trying to force the deserializer to reconstruct it as a list - that's not going to work.

You will need to either:

  1. Return the list itself in your GetResults() method (ie change it from MyResponse to List<MyType>, OR
  2. On the client side, convert the data received to type MyResponse, instead of List<MyType>.

Upvotes: 1

Related Questions