2

I am having trouble deserializing a json response. I am using the Refit c# library to communicate with the API. The RootObject.company in response is always null, even though the test field is loaded correctly. I also tried retrieving the JSON string via Postman and deserializing it manually to see if there would be a problem, but it works as expected. I am stumped at what could be going wrong. The same code did work previously with a list of companies, but the design changed and now only a single company is returned. Please ignore the login part, it is there merely for authentication into my local dev backend. I created a minimum working example of my problem:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Hello World!");

        var ApiIlogin = RestService.For<IMyInterface>("http://localhost:8000");
        var login = ApiIlogin.Login("admin", "admin").Result;

        var result = ApiIlogin.GetData(login.Token).Result;

        var myString =
            "{\"company\":{\"id\":1,\"name\":\"TestComp\",\"farms\":[{\"id\":1,\"name\":\"TestFarm1\",\"cameras\":[{\"id\":1,\"name\":\"FakeCamera\",\"ipAddress\":\"127.0.0.1\",\"farm\":1,\"port\":8666,\"count\":[],\"weight\":[],\"area\":null}],\"company\":1},{\"id\":3,\"name\":\"TestFarm3\",\"cameras\":[],\"company\":1}]},\"test\":\"Test\"}";
        var test = JsonSerializer.Deserialize<Rootobject>(myString);
    }
}

public interface IMyInterface
{
    [Get("/api/data")]
    Task<Rootobject> GetData([Authorize] string token);

    [Post("/api/login?username={username}&password={password}")]
    Task<LoginUserResponse> Login(string username, string password);
}

public class LoginUserResponse
{
    [JsonNumberHandling(JsonNumberHandling.AllowReadingFromString)]
    public int Id { get; set; }

    public string Username { get; set; }
    public IList<string> Roles { get; set; }
    public string Token { get; set; }
    public bool Authenticated { get; set; }
}

public class Rootobject
{
    public Company company { get; set; }
    public string test { get; set; }
}

public class Company
{
    public int id { get; set; }
    public string name { get; set; }
    public Farm[] farms { get; set; }
}

public class Farm
{
    public int id { get; set; }
    public string name { get; set; }
    public Camera[] cameras { get; set; }
    public int company { get; set; }
}

public class Camera
{
    public int id { get; set; }
    public string name { get; set; }
    public string ipAddress { get; set; }
    public int farm { get; set; }
    public int port { get; set; }
    public object[] count { get; set; }
    public object[] weight { get; set; }
    public object area { get; set; }
}

And here is an example JSON retrieved by Postman, just in case the inlined message makes a difference.

{
    "company": {
        "id": 1,
        "name": "TestComp",
        "farms": [
            {
                "id": 1,
                "name": "TestFarm1",
                "cameras": [
                    {
                        "id": 1,
                        "name": "FakeCamera",
                        "ipAddress": "127.0.0.1",
                        "farm": 1,
                        "port": 8666,
                        "count": [],
                        "weight": [],
                        "area": null
                    }
                ],
                "company": 1
            },
            {
                "id": 3,
                "name": "TestFarm3",
                "cameras": [],
                "company": 1
            }
        ],
        "__initializer__": null,
        "__cloner__": null,
        "__isInitialized__": true
    },
    "test": "Test"
}
Luk164
  • 657
  • 8
  • 22
  • Are you certain that the Rootobject class structure that you have defined has been updated to account for the changes to the response that you have mentioned? I was able to throw together a quick project locally based on the details that you provided and deserialization appears to be working as expected. – mreyeros Jul 01 '21 at 12:30
  • @mreyeros I literally generated these classes using VC2019 "Paste JSON as Classes" feature to make sure they fit. – Luk164 Jul 01 '21 at 12:51
  • @mreyeros Nevermind, found out what was wrong. – Luk164 Jul 01 '21 at 13:03

1 Answers1

3

Nevermind, I found the problem. I forgot that the admin account does not have a company assigned to it, so logging in with that account and retrieving the data returned null. On Postman I am using a user account made specifically for testing which does have a company assigned, so the response came out as expected. I am going to throw a warning into my API just in case my future self does this again.

In other words, this was a classic PEBKaC.

Luk164
  • 657
  • 8
  • 22