null object when deserializing Json

3

I make a request to an API, which returns me data in the form of JSON.

Example:

{
"id": 8452,
"creator_user_id": {
"id": 46342,
"name": "ADM. Suporte Comercial",
"email": "*******@gmail.com",
"has_pic": true,
"pic_hash": "296e6514a7d0bf854fdcf22e60a19c9f",
"active_flag": false,
"value": 46342
},
"user_id": {
"id": 1875524,
"name": "09. Natália Grosso",
"email": "*******@gmail.com",
"has_pic": true,
"pic_hash": "e4f326a72bc341c84e7608993435c509",
"active_flag": true,
"value": 1875524
},
"person_id": {
"name": "Eng. Simone Biolo",
"email": [
{
"label": "work",
"value": "*******@gmail.com",
"primary": true
}
],
"phone": [
{
"label": "work",
"value": "***********",
"primary": true
}
],
"value": 10044
},
"org_id": null,
"stage_id": 45,
"title": "161366 - Lavatório Cirúrgico (cópia)",
"value": 25980,
"currency": "BRL",
"add_time": "2017-05-29 12:12:54",
"update_time": "2017-08-02 17:38:47",
"stage_change_time": "2017-07-24 11:52:56",
"active": true,
"deleted": false,
"status": "open",
"next_activity_date": "2017-08-16",
"next_activity_time": null,
"next_activity_id": 42869,
"last_activity_id": null,
"last_activity_date": null,
"lost_reason": null,
"visible_to": "3",
"close_time": null,
"pipeline_id": 6,
"won_time": null,
"first_won_time": null,
"lost_time": null,
"products_count": 0,
"files_count": 0,
"notes_count": 0,
"followers_count": 1,
"email_messages_count": 0,
"activities_count": 1,
"done_activities_count": 0,
"undone_activities_count": 1,
"reference_activities_count": 0,
"participants_count": 1,
"ac0ad7297e4688aec9d739f3bcc123d0e783b615": "53,25",
"4c67dc6df0ef9892524aae24f65c28dc11d3b765": "41",
"last_incoming_mail_time": null,
"last_outgoing_mail_time": null,
"stage_order_nr": 4,
"person_name": "Eng. Simone Biolo",
"org_name": null,
"next_activity_subject": "Instalação",
"next_activity_type": "call",
"next_activity_duration": null,
"next_activity_note": "Previsão de instalação em 15/08",
"formatted_value": "R$****",
"rotten_time": null,
"weighted_value": 0,
"formatted_weighted_value": "R$0",
"owner_name": "09. Natália Grosso",
"cc_email": "******@pipedrivemail.com",
"org_hidden": false,
"person_hidden": false
}

Then, I copied, and I used the special VS paste: Paste JSON as Class , which generated me Model below:

public class Projetos
{
    [Key]
    public int id { get; set; }
    public Creator_User_Id creator_user_id { get; set; }
    public User_Id user_id { get; set; }
    public Person_Id person_id { get; set; }
    public object org_id { get; set; }
    public int stage_id { get; set; }
    public string title { get; set; }
    public int value { get; set; }
    public string currency { get; set; }
    public string add_time { get; set; }
    public string update_time { get; set; }
    public string stage_change_time { get; set; }
    public bool active { get; set; }
    public bool deleted { get; set; }
    public string status { get; set; }
    public string next_activity_date { get; set; }
    public object next_activity_time { get; set; }
    public int next_activity_id { get; set; }
    public object last_activity_id { get; set; }
    public object last_activity_date { get; set; }
    public object lost_reason { get; set; }
    public string visible_to { get; set; }
    public object close_time { get; set; }
    public int pipeline_id { get; set; }
    public object won_time { get; set; }
    public object first_won_time { get; set; }
    public object lost_time { get; set; }
    public int products_count { get; set; }
    public int files_count { get; set; }
    public int notes_count { get; set; }
    public int followers_count { get; set; }
    public int email_messages_count { get; set; }
    public int activities_count { get; set; }
    public int done_activities_count { get; set; }
    public int undone_activities_count { get; set; }
    public int reference_activities_count { get; set; }
    public int participants_count { get; set; }
    public object ac0ad7297e4688aec9d739f3bcc123d0e783b615 { get; set; }
    public string _4c67dc6df0ef9892524aae24f65c28dc11d3b765 { get; set; }
    public object last_incoming_mail_time { get; set; }
    public object last_outgoing_mail_time { get; set; }
    public int stage_order_nr { get; set; }
    public string person_name { get; set; }
    public object org_name { get; set; }
    public string next_activity_subject { get; set; }
    public string next_activity_type { get; set; }
    public object next_activity_duration { get; set; }
    public string next_activity_note { get; set; }
    public string formatted_value { get; set; }
    public object rotten_time { get; set; }
    public int weighted_value { get; set; }
    public string formatted_weighted_value { get; set; }
    public string owner_name { get; set; }
    public string cc_email { get; set; }
    public bool org_hidden { get; set; }
    public bool person_hidden { get; set; }
}

public class Creator_User_Id
{
    public int id { get; set; }
    public string name { get; set; }
    public string email { get; set; }
    public bool has_pic { get; set; }
    public string pic_hash { get; set; }
    public bool active_flag { get; set; }
    public int value { get; set; }
}

public class User_Id
{
    public int id { get; set; }
    public string name { get; set; }
    public string email { get; set; }
    public bool has_pic { get; set; }
    public string pic_hash { get; set; }
    public bool active_flag { get; set; }
    public int value { get; set; }
}

public class Person_Id
{
    public string name { get; set; }
    public Email[] email { get; set; }
    public Phone[] phone { get; set; }
    public int value { get; set; }
}

public class Email
{
    public string label { get; set; }
    public string value { get; set; }
    public bool primary { get; set; }
}

public class Phone
{
    public string label { get; set; }
    public string value { get; set; }
    public bool primary { get; set; }
}

I make Request via HttpClient :

  public class ProjetosController : Controller
{
    private static HttpClient httpClient;

    static ProjetosController()
    {
        httpClient = new HttpClient();
        httpClient.BaseAddress = new Uri("https://*****.pipedrive.com/v1/");
        httpClient.DefaultRequestHeaders.Accept.Clear();
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        //Se precisar adicionar alguma autenticação, faça o aqui.        
    }

    [HttpGet]
    public async Task<ActionResult> Index()
    {           
        var queryString = $"deals?stage_id=45&status=open&start=0&api_token=************************22f3a2c";
        var response = await httpClient.GetAsync(queryString);
        if (response.IsSuccessStatusCode)
        {
            var json = await response.Content.ReadAsStringAsync();                
            var model = Newtonsoft.Json.JsonConvert.DeserializeObject<Projetos>(json);
            return Json(model, JsonRequestBehavior.AllowGet);
        }
        return new HttpStatusCodeResult(HttpStatusCode.InternalServerError, "Erro ao acessar a API.");
    }
}

However, running DeserializeObject returns all objects as null

Returnfromvarjson=awaitresponse.Content.ReadAsStringAsync();

Whentryingtorunthe@LINQemployeesolution,theexceptionbelowisgenerated:

    
asked by anonymous 11.08.2017 / 21:08

2 answers

4

The problem is that JSON is not in the format you have specified.

I have just seen the PipeDrive API v1 documentation and it says that the response format for requests to the deals resource (using the GET verb) is like this:

{
    "success": true,
    "data": null,
    "additional_data": {
        "pagination": {
            "start": 0,
            "limit": 100,
            "more_items_in_collection": false
        }
    }
}

That is, there is no relationship between the target serialization model and the payload received from the request.

What I would tell you is to create a model to represent the PipeDrive API responses.

I made it generic, because it is very likely that the answer will be like this for all resources.

class PipeDriveResponse<T> where T : new()
{
    public bool Success { get; set; }
    public T Data { get; set; }
    public DadosAdicionais AdditionalData { get; set; }       
}

class DadosAdicionais
{
    public Paginacao { get; set; }
}

class Paginacao
{
    public int Start { get; set; }
    public int Limit { get; set; }
    public bool MoreItensInCollection { get; set; }
}

And, in the deletion, it will be necessary to change the type:

// resto do código
var model = JsonConvert.DeserializeObject<PipeDriveResponse<Projetos>>(json);
// resto do código
  

Disclaimer : I do not know how the deserter is configured, so I wrote the classes with the names of the properties in TitleCasing. Maybe then you need to adapt the properties name. Either way, the idea remains exactly the same.

    
11.08.2017 / 22:18
1

I had no problem consuming your JSON.

I've set up a POC GIT as well.

static void Main(string[] args)
{
    {
        string path = @"C:\work\stackoverflow\stackoverflow\ConsoleApp1\bin\Debug\new 1.txt";
        // Open the file to read from.
        string readText = File.ReadAllText(path);

        var model = Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject>(readText);
    }
}

Only the classes I generated by here .

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    public class CreatorUserId
    {
        public int id { get; set; }
        public string name { get; set; }
        public string email { get; set; }
        public bool has_pic { get; set; }
        public string pic_hash { get; set; }
        public bool active_flag { get; set; }
        public int value { get; set; }
    }

    public class UserId
    {
        public int id { get; set; }
        public string name { get; set; }
        public string email { get; set; }
        public bool has_pic { get; set; }
        public string pic_hash { get; set; }
        public bool active_flag { get; set; }
        public int value { get; set; }
    }

    public class Email
    {
        public string label { get; set; }
        public string value { get; set; }
        public bool primary { get; set; }
    }

    public class Phone
    {
        public string label { get; set; }
        public string value { get; set; }
        public bool primary { get; set; }
    }

    public class PersonId
    {
        public string name { get; set; }
        public List<Email> email { get; set; }
        public List<Phone> phone { get; set; }
        public int value { get; set; }
    }

    public class RootObject
    {
        public int id { get; set; }
        public CreatorUserId creator_user_id { get; set; }
        public UserId user_id { get; set; }
        public PersonId person_id { get; set; }
        public object org_id { get; set; }
        public int stage_id { get; set; }
        public string title { get; set; }
        public int value { get; set; }
        public string currency { get; set; }
        public string add_time { get; set; }
        public string update_time { get; set; }
        public string stage_change_time { get; set; }
        public bool active { get; set; }
        public bool deleted { get; set; }
        public string status { get; set; }
        public string next_activity_date { get; set; }
        public object next_activity_time { get; set; }
        public int next_activity_id { get; set; }
        public object last_activity_id { get; set; }
        public object last_activity_date { get; set; }
        public object lost_reason { get; set; }
        public string visible_to { get; set; }
        public object close_time { get; set; }
        public int pipeline_id { get; set; }
        public object won_time { get; set; }
        public object first_won_time { get; set; }
        public object lost_time { get; set; }
        public int products_count { get; set; }
        public int files_count { get; set; }
        public int notes_count { get; set; }
        public int followers_count { get; set; }
        public int email_messages_count { get; set; }
        public int activities_count { get; set; }
        public int done_activities_count { get; set; }
        public int undone_activities_count { get; set; }
        public int reference_activities_count { get; set; }
        public int participants_count { get; set; }
        public string ac0ad7297e4688aec9d739f3bcc123d0e783b615 { get; set; }
        public string __invalid_name__4c67dc6df0ef9892524aae24f65c28dc11d3b765 { get; set; }
        public object last_incoming_mail_time { get; set; }
        public object last_outgoing_mail_time { get; set; }
        public int stage_order_nr { get; set; }
        public string person_name { get; set; }
        public object org_name { get; set; }
        public string next_activity_subject { get; set; }
        public string next_activity_type { get; set; }
        public object next_activity_duration { get; set; }
        public string next_activity_note { get; set; }
        public string formatted_value { get; set; }
        public object rotten_time { get; set; }
        public int weighted_value { get; set; }
        public string formatted_weighted_value { get; set; }
        public string owner_name { get; set; }
        public string cc_email { get; set; }
        public bool org_hidden { get; set; }
        public bool person_hidden { get; set; }
    }
}
    
11.08.2017 / 21:52