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 ofWebClient
- Avoiding nested classes unless you really need to