Search code examples
c#json.netsystem.text.jsonosrm

JsonSerializer.Deserialize returns an empty object with null properties


I try to parse a response by the OSRM map matching service using the following code (here a .NET Fiddle too; UPDATED with fixed version):

namespace OsrmMapMatch
{
    public class OsrmResponse
    {
        public string code;
        public OsrmLeg[] legs;
    }

    public class OsrmLeg
    {
        public OsrmAnnotation annotation;
    }

    public class OsrmAnnotation
    {
        public uint[] nodes;
    }

    internal class Program
    {
        static async Task Main(string[] args)
        {
            const string HttpClientMapMatch = "HttpClientMapMatch";
            const string OsrmUri = "10.757938,52.437444;10.764379,52.437314;10.770562,52.439067;10.773268,52.436633?overview=simplified&radiuses=50;50;50;50&generate_hints=false&skip_waypoints=true&gaps=ignore&annotations=nodes&geometries=geojson";

            ServiceProvider serviceProvider = new ServiceCollection()
                .AddHttpClient(HttpClientMapMatch, httpClient =>
                {
                    httpClient.BaseAddress = new Uri("https://router.project-osrm.org/match/v1/driving/");
                }).Services.BuildServiceProvider();

            IHttpClientFactory httpClientFactory = serviceProvider.GetService<IHttpClientFactory>();

            HttpClient httpClient = httpClientFactory.CreateClient(HttpClientMapMatch);

            HttpResponseMessage response = await httpClient.GetAsync(OsrmUri);
            if (response.IsSuccessStatusCode) 
            {
                string stringData = await response.Content.ReadAsStringAsync();
                OsrmResponse osrmResponse = JsonSerializer.Deserialize<OsrmResponse>(stringData);
                Console.WriteLine($"OsrmResponse: {JsonSerializer.Serialize(osrmResponse)}");
            }
        }
    }
}

Unfortunately, the returned object is empty, its code and legs properties are null:

VS 2022 screenshot

I have tried the following change with no success:

JsonSerializerOptions options = new()
{
    PropertyNameCaseInsensitive = true
};
OsrmResponse osrmResponse = JsonSerializer.Deserialize<OsrmResponse>(stringData, options);

What could be the reason for the failing JSON parsing?

How do you debug such problems in general?

I would like to use Microsoft's System.Text.Json and do not want to use Newtonsoft.JSON.

I only need the OSM nodes array at the end, that is why I have omitted other members in the response.


Solution

  • Based on the response, your model should look like below. The simplest way to generate the model is using Visual Studio->Edit->Paste Special->Paste Json as Classes or any other Online tools like json2csharp. Once you update the model your code should work.

    public class Annotation
    {
        public List<object> nodes { get; set; }
    }
    
    public class Geometry
    {
        public List<List<double>> coordinates { get; set; }
        public string type { get; set; }
    }
    
    public class Leg
    {
        public List<object> steps { get; set; }
        public string summary { get; set; }
        public double weight { get; set; }
        public double duration { get; set; }
        public Annotation annotation { get; set; }
        public double distance { get; set; }
    }
    
    public class Matching
    {
        public double confidence { get; set; }
        public Geometry geometry { get; set; }
        public List<Leg> legs { get; set; }
        public string weight_name { get; set; }
        public double weight { get; set; }
        public double duration { get; set; }
        public double distance { get; set; }
    }
    
    public class OsrmResponse
    {
        public string code { get; set; }
        public List<Matching> matchings { get; set; }
    }