Search code examples
c#jsonjson.netdeserializationjson-deserialization

Problem trying to deserialize a json with a model


I am trying to deserialize a json (using Newtonsoft.Json), i created the classes, but in json code there is a variable that i don't know if it is corrected or i don't know how to deserialize.

I am getting a null exception on line : MessageBox.Show(root.matriculations._14000.name)

    private void btnImportaDados_Click(object sender, EventArgs e)
    {

        string getDataUrl = "https://xxx.xxx.com/api/matriculations/get.json?entity_code=14000";

        try
        {
            using (var webClient = new System.Net.WebClient())
            {
                var json = webClient.DownloadString(getDataUrl);

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

                MessageBox.Show(root.matriculations._14000.name);
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }

    }


    public class Rootobject
    {
        public Matriculations matriculations { get; set; }
    }

    public class Matriculations
    {
        public _14000 _14000 { get; set; }
    }

    public class _14000
    {
        public string entity_code { get; set; }
        public string name { get; set; }
        public string street { get; set; }
        public string local { get; set; }
        public string postal_code { get; set; }
        public string sub_postal_code { get; set; }
        public string phone1 { get; set; }
        public object phone2 { get; set; }
        public string email1 { get; set; }
        public object email2 { get; set; }
        public string entity_code_2 { get; set; }
        public string courseaction_ref { get; set; }
        public string courseaction_id { get; set; }
        public string course_code { get; set; }
        public string course { get; set; }
        public Billingorderplan[] billingorderplans { get; set; }
    }

    public class Billingorderplan
    {
        public string id { get; set; }
        public string paid { get; set; }
        public string date { get; set; }
        public object obs { get; set; }
        public object payment_doc_num { get; set; }
        public string value { get; set; }
        public string description { get; set; }
        public string entity_code { get; set; }
        public object paid_date { get; set; }
    }

The result(json data) from the url is:

{"matriculations":{"14000":{"entity_code":"14000","name":"Fabio Danilson Sivone Antonio","street":"Rua Dr. Pereira Jardim, Bl. 3 - 25 - 4 B","local":"Luanda","postal_code":"2685","sub_postal_code":"093","phone1":"923810539","phone2":null,"email1":"[email protected]","email2":null,"entity_code_2":"9957","courseaction_ref":"EPCE_01","courseaction_id":"1828","course_code":"EPCE","course":"Especializa\u00e7\u00e3o Avan\u00e7ada em Investiga\u00e7\u00e3o de Crime Econ\u00f3mico [E-learning]","billingorderplans":[{"id":"298","paid":"0","date":"2020-05-06","obs":null,"payment_doc_num":null,"value":"0.00","description":"Inscri\u00e7\u00e3o","entity_code":"14000","paid_date":null},{"id":"299","paid":"0","date":"2019-11-21","obs":null,"payment_doc_num":null,"value":"0.00","description":"1\u00aa presta\u00e7\u00e3o","entity_code":"14000","paid_date":null},{"id":"300","paid":"0","date":"2019-12-08","obs":null,"payment_doc_num":null,"value":"0.00","description":"2\u00aa presta\u00e7\u00e3o","entity_code":"14000","paid_date":null},{"id":"301","paid":"0","date":"2020-01-08","obs":null,"payment_doc_num":null,"value":"0.00","description":"3\u00aa presta\u00e7\u00e3o","entity_code":"14000","paid_date":null},{"id":"302","paid":"0","date":"2020-02-08","obs":null,"payment_doc_num":null,"value":"0.00","description":"4\u00aa presta\u00e7\u00e3o","entity_code":"14000","paid_date":null},{"id":"303","paid":"0","date":"2020-03-08","obs":null,"payment_doc_num":null,"value":"0.00","description":"5\u00aa presta\u00e7\u00e3o","entity_code":"14000","paid_date":null},{"id":"304","paid":"0","date":"2020-04-08","obs":null,"payment_doc_num":null,"value":"0.00","description":"6\u00aa presta\u00e7\u00e3o","entity_code":"14000","paid_date":null},{"id":"305","paid":"0","date":"2020-05-08","obs":null,"payment_doc_num":null,"value":"0.00","description":"7\u00aa presta\u00e7\u00e3o","entity_code":"14000","paid_date":null},{"id":"306","paid":"0","date":"2020-06-08","obs":null,"payment_doc_num":null,"value":"0.00","description":"8\u00aa presta\u00e7\u00e3o","entity_code":"14000","paid_date":null},{"id":"16595","paid":"0","date":"2020-08-27","obs":null,"payment_doc_num":null,"value":"20.00","description":"EExt - Atividade","entity_code":"14000","paid_date":null},{"id":"16596","paid":"0","date":"2020-08-27","obs":null,"payment_doc_num":null,"value":"45.00","description":"EExt - Teste","entity_code":"14000","paid_date":null},{"id":"16597","paid":"0","date":"2020-08-27","obs":null,"payment_doc_num":null,"value":"20.00","description":"EExt - Atividade","entity_code":"14000","paid_date":null},{"id":"16598","paid":"0","date":"2020-08-27","obs":null,"payment_doc_num":null,"value":"45.00","description":"EExt - Teste","entity_code":"14000","paid_date":null},{"id":"16599","paid":"0","date":"2020-08-27","obs":null,"payment_doc_num":null,"value":"20.00","description":"EExt - Atividade","entity_code":"14000","paid_date":null},{"id":"16601","paid":"0","date":"2020-08-27","obs":null,"payment_doc_num":null,"value":"45.00","description":"EExt - Teste","entity_code":"14000","paid_date":null},{"id":"16600","paid":"0","date":"2020-08-27","obs":null,"payment_doc_num":null,"value":"20.00","description":"EExt - Atividade","entity_code":"14000","paid_date":null}]}}}

But that "14000" is a varible value depending from the parameter passed.

How can i do it?

Thank You.


Solution

  • Since 14000 cannot be a variable name you will have to resort to some manual intervention to capture that dynamic value. The cleanest way is to remove the Matriculations class and replace it with Dictionary<int, _14000> (or Dictionary<string, _14000>).

    public class Rootobject
    {
        public Dictionary<int, _14000> matriculations { get; set; }
    }
    

    This will ensure that the key is captured correctly even if it is a number. You can read the object from the dictionary's values as such: root.matriculations.Values.First().name. (Remember to import System.Linq for using .First().)

    For clarity you can rename _14000 to something more descriptive.