0

I'm making a call to an external api service, however i am getting an exception and it wont deserilize into my model:

my response is

[
    {
        "$type": "Tfl.Api.Presentation.Entities.RoadCorridor, Tfl.Api.Presentation.Entities",
        "id": "a2",
        "displayName": "A2",
        "statusSeverity": "Good",
        "statusSeverityDescription": "No Exceptional Delays",
        "bounds": "[[-0.0857,51.44091],[0.17118,51.49438]]",
        "envelope": "[[-0.0857,51.44091],[-0.0857,51.49438],[0.17118,51.49438],[0.17118,51.44091],[-0.0857,51.44091]]",
        "url": "/Road/a2"
    }
]

and my code is

 public class TravelService : ITravelService
    {
        string baseURL = "https://foo.bar/blah.blah";

        private readonly IMapToNew<Road, RoadDto> _mapper;
        public TravelService()
        {

        }


        public TravelService(IMapToNew<Road, RoadDto> mapper)
        {
            _mapper = mapper;
        }

        public async Task<RoadDto> GetTravelInformation()
        {
            var road = GetRoad();

            Console.WriteLine(road.Result.DisplayName);

            return new RoadDto
            {
                DisplayName = road.Result.DisplayName,
                StatusSeverityDescription = road.Result.DisplayName,
                StatusSeverity = road.Result.DisplayName
            };
        }


        private async Task <Road> GetRoad()
        {
            HttpClient client = new HttpClient();
            client.BaseAddress = new Uri(baseURL);

            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            HttpResponseMessage Res = await client.GetAsync(baseURL);

            if (Res.IsSuccessStatusCode)
            {
                var roadResponse = Res.Content.ReadAsStringAsync().Result;

                Road road = JsonConvert.DeserializeObject<Road>(roadResponse);
                return new Road
                {
                    DisplayName = road.DisplayName,
                    StatusSeverity = road.StatusSeverity,
                    StatusSeverityDescription = road.StatusSeverityDescription
                };
            }

            return new Road { };
        }


    }

my road class is:

public class Road
{
    [JsonProperty(PropertyName = "$type")]
    public string PropertyName { get; set; }
    public string Id { get; set; }
    public string DisplayName { get; set; }
    public string StatusSeverity { get; set; }
    public string StatusSeverityDescription { get; set; }
    public string Bounds { get; set; }
    public string Envelope { get; set; }
    public string Url { get; set; }
}

when i run my code i'm getting an exception: 'One or more errors occurred. (One or more errors occurred. (Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'Travel.Responses.Road' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly

dros
  • 1,217
  • 2
  • 15
  • 31
  • can you post you Road class? – jasonmchoe Dec 13 '19 at 17:05
  • 1
    I would start at [removing *all* the `.Result`s](https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html). – GSerg Dec 13 '19 at 17:05
  • @jasonmchoe see edit :) – dros Dec 13 '19 at 17:07
  • add `[JsonProperty]` and provide property name for all properties. – MD. Khairul Basar Dec 13 '19 at 17:08
  • 2
    You need to use `JsonConvert.DeserializeObject>` since the JSON is an array. Also, `"$type"` is a reserved property name in Json.NET representing a polymorphic subtype. You can ignore it if you don't care about polymorphism. – dbc Dec 13 '19 at 17:09
  • @MD.KhairulBasar - that's not necessary as long as the JSON and c# properties are the same modulo case. Json.NET is a case-insensitive deserializer. – dbc Dec 13 '19 at 17:10
  • @dbc that would require me to modify Road to a list also, no? – dros Dec 13 '19 at 17:13
  • regardless of the above comments, the `bounds` and `envelope` fields on the raw JSON are typed as strings, but contain a JSON-encoded array of arrays. See @StriplingWarrior's answer – Josh E Dec 13 '19 at 17:14
  • @AndyStav - well an array of `RoadCorridor` objects is being returned, so yes. Alternatively you could do `JsonConvert.DeserializeObject>(roadResponse).Single()` if you are certain that exactly one road is being returned. – dbc Dec 13 '19 at 17:15
  • Looks to be a duplicate of [Cannot deserialize the JSON array (e.g. `[1,2,3]`) into type ' ' because type requires JSON object (e.g. `{“name”:“value”}`) to deserialize correctly](https://stackoverflow.com/q/22557559/3744182); agree? – dbc Dec 13 '19 at 17:18

2 Answers2

1

As the exception message explains, you're trying to deserialize into a Road, but the payload is actually a JSON array that contains a Road inside of it. You could do something like this:

var roads = JsonConvert.DeserializeObject<Road[]>(roadResponse);
var road = roads.Single(); // assuming you know the array only has one entry
StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315
0
   List<Road> road = JsonConvert.DeserializeObject<List<Road>>(roadResponse);

this worked for me!

thanks all

dros
  • 1,217
  • 2
  • 15
  • 31