Home > Blockchain >  Json failing to parse
Json failing to parse

Time:04-13

I have the following JSON string coming back from an API

{"success":true,"data":[
{"id":6,"order_nr":1,"name":"Capture Details","active_flag":true,"deal_probability":100,"pipeline_id":2,"rotten_flag":false,"rotten_days":null,"add_time":"2022-02-09 12:22:26","update_time":"2022-03-14 12:42:16","pipeline_name":"Stove Sales","pipeline_deal_probability":true},
{"id":19,"order_nr":2,"name":"Survey","active_flag":true,"deal_probability":100,"pipeline_id":2,"rotten_flag":false,"rotten_days":null,"add_time":"2022-02-15 13:45:03","update_time":"2022-03-14 12:42:16","pipeline_name":"Stove Sales","pipeline_deal_probability":true},
{"id":9,"order_nr":3,"name":"Quote","active_flag":true,"deal_probability":100,"pipeline_id":2,"rotten_flag":false,"rotten_days":null,"add_time":"2022-02-09 12:22:26","update_time":"2022-03-14 12:42:16","pipeline_name":"Stove Sales","pipeline_deal_probability":true},
{"id":10,"order_nr":4,"name":"Deposit Paid","active_flag":true,"deal_probability":100,"pipeline_id":2,"rotten_flag":false,"rotten_days":null,"add_time":"2022-02-09 12:22:26","update_time":"2022-03-14 12:42:16","pipeline_name":"Stove Sales","pipeline_deal_probability":true},
{"id":11,"order_nr":5,"name":"Order Stove","active_flag":true,"deal_probability":100,"pipeline_id":2,"rotten_flag":false,"rotten_days":null,"add_time":"2022-02-09 12:22:26","update_time":"2022-03-14 12:42:16","pipeline_name":"Stove Sales","pipeline_deal_probability":true},
{"id":12,"order_nr":6,"name":"Contract Agreed","active_flag":true,"deal_probability":100,"pipeline_id":2,"rotten_flag":false,"rotten_days":null,"add_time":"2022-02-09 12:22:26","update_time":"2022-03-14 12:42:16","pipeline_name":"Stove Sales","pipeline_deal_probability":true},
{"id":20,"order_nr":7,"name":"Send Full Ts&Cs for reply","active_flag":true,"deal_probability":100,"pipeline_id":2,"rotten_flag":false,"rotten_days":null,"add_time":"2022-03-14 12:42:16","update_time":"2022-03-14 12:42:16","pipeline_name":"Stove Sales","pipeline_deal_probability":true},
{"id":13,"order_nr":8,"name":"Install Stove","active_flag":true,"deal_probability":100,"pipeline_id":2,"rotten_flag":false,"rotten_days":null,"add_time":"2022-02-09 12:22:26","update_time":"2022-03-14 12:42:16","pipeline_name":"Stove Sales","pipeline_deal_probability":true},
{"id":14,"order_nr":9,"name":"Send Review","active_flag":true,"deal_probability":100,"pipeline_id":2,"rotten_flag":false,"rotten_days":null,"add_time":"2022-02-09 12:22:26","update_time":"2022-03-14 12:42:16","pipeline_name":"Stove Sales","pipeline_deal_probability":true},
{"id":15,"order_nr":1,"name":"Awaiting Sweep","active_flag":true,"deal_probability":100,"pipeline_id":3,"rotten_flag":false,"rotten_days":null,"add_time":"2022-02-12 17:57:35","update_time":"2022-02-12 17:57:35","pipeline_name":"Sweeps","pipeline_deal_probability":true},
{"id":16,"order_nr":2,"name":"Sweep Booked","active_flag":true,"deal_probability":100,"pipeline_id":3,"rotten_flag":false,"rotten_days":null,"add_time":"2022-02-12 17:57:35","update_time":"2022-02-12 17:57:35","pipeline_name":"Sweeps","pipeline_deal_probability":true},
{"id":17,"order_nr":3,"name":"Sweep","active_flag":true,"deal_probability":100,"pipeline_id":3,"rotten_flag":false,"rotten_days":null,"add_time":"2022-02-12 17:57:35","update_time":"2022-02-12 17:57:35","pipeline_name":"Sweeps","pipeline_deal_probability":true},
{"id":18,"order_nr":4,"name":"Send Review","active_flag":true,"deal_probability":100,"pipeline_id":3,"rotten_flag":false,"rotten_days":null,"add_time":"2022-02-12 17:57:35","update_time":"2022-02-12 17:57:35","pipeline_name":"Sweeps","pipeline_deal_probability":true}
]}

Newlines added by me whilst checking the format looked OK. My C# data class looks like this

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

namespace PipedriveClient
{
    internal class PipedriveStage
    {
        // Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse);
        public class Datum
        {
            public int id { get; set; }
            public int order_nr { get; set; }
            public string name { get; set; }
            public bool active_flag { get; set; }
            public int deal_probability { get; set; }
            public int pipeline_id { get; set; }
            public bool rotten_flag { get; set; }
            public object rotten_days { get; set; }
            public string add_time { get; set; }
            public string update_time { get; set; }
            public string pipeline_name { get; set; }
            public bool pipeline_deal_probability { get; set; }
        }

        public class Root
        {
            public bool success { get; set; }
            public List<Datum> data { get; set; }
        }


    }
}

The code trying to parse it looks like

    List<PipedriveStage.Root> stages;

    using (var webClient = new WebClient())
    {
        var response = webClient.DownloadString(url);
        JObject result = JObject.Parse(response);
        var data = result.SelectToken("data");
        stages = JsonConvert.DeserializeObject<List<PipedriveStage.Root>>(data.ToString());
    }

Checking the value of response the response string returned from by webClient is identical, so I'm confident it ought to parse OK. My class I got by using json2csharp.com and the same basic code is working fine for other returns from the same API. I must just be missing something trivially obvious, which I'm hoping will leap out at one of you guys!

CodePudding user response:

Your JSON directly represents a PipedriveStage.Root object. For some reason you're parsing to JObject, selecting the data token (which is an array, but of Datum), converting that back to a string and then parsing it as if it were a List<Root>.

You can change your code to just:

var root = JsonConvert.DeserializeObject<PipedriveStage.Root>(response);

(Your stages variable isn't useful here - you don't logically have multiple roots to deserialize to.)

I would also recommend:

  • Changing the property names to be idiomatic C#, using [JsonProperty] to indicate how they're represented in JSON. That will make your C# code look more "normal". (json2csharp.com has checkboxes for "Use Pascal Case" and "Add JsonProperty Attributes" that make this trivial.)
  • Using HttpClient instead of WebClient
  • Avoiding nested classes unless you really need to
  • Related