Deserialization Json to C# using Newtonsoft - c#

I have the following JSON that I need to parse :
{
"code": 200,
"status": "OK",
"response": {
"course_accessJSON": null,
"in_progress": 1,
"completed": 0,
"passed": 0,
"location": "http://*************************************",
"subscription": {
"started": 1465834293,
"expired": 1473869493,
"payment": "account"
},
"is_expired": false,
"course_progress": {
"CMP1044": {
"course_name_en": "Java Programming",
"no_of_lessons": 30,
"viewed": 1,
"viewed_start": 1465834789,
"viewed_end": null,
"cert_attemptsCSV": null,
"cert_resetsCSV": null,
"cert_serial": null,
"high_score": null,
"location": "http://***************************"
}
}
}
}
I have managed to get all the elements out except the value in the course_progress item using the following:
SampleResourse obj = JsonConvert.DeserializeObject<SampleResourse>(s);
Response.Write(obj.Response.CourseProgress.CMP1044.CourseNameEn.ToString());
class SampleResourse
{
[JsonProperty("code")]
public int respcode { get; set; }
[JsonProperty("status")]
public string respStatus { get; set; }
[JsonProperty("response")]
public Response2 Response { get; set; }
}
class Response2
{
[JsonProperty("in_progress")]
public int InProgress { get; set; }
[JsonProperty("completed")]
public int Completed { get; set; }
[JsonProperty("passed")]
public int Passed { get; set; }
[JsonProperty("course_progress")]
public CourseProgress CourseProgress { get; set; }
}
class CourseProgress
{
[JsonProperty("CMP1044")]
public CMP10442 CMP1044 { get; set; }
}
class CMP10442
{
[JsonProperty("course_name_en")]
public string CourseNameEn { get; set; }
}
I need the elements course_name_en, no_of_lessons,viewed however there will be multiple properties similar to "CMP1044". Each "CMP" property will have a unique number. I want to list progress on each.

Simply change the following :
class Response2
{
[JsonProperty("in_progress")]
public int InProgress { get; set; }
[JsonProperty("completed")]
public int Completed { get; set; }
[JsonProperty("passed")]
public int Passed { get; set; }
[JsonProperty("course_progress")]
public Dictionary<string, CourseProgress> CourseProgress { get; set; }
}
class CourseProgress
{
[JsonProperty("course_name_en")]
public string CourseNameEn { get; set; }
}
To list the course name along with the id, you can do this:
var resource = Newtonsoft.Json.JsonConvert.DeserializeObject<SampleResourse>(json);
foreach (var kvp in resource.Response.CourseProgress)
{
Response.Write(kvp.Key + ":" + kvp.Value.CourseNameEn + Environment.NewLine);
}

Related

how can I preserve this json format, while adding to it before serializing it?

I have a fairly complex json file I am deserializing into a datatable to be displayed to datgridview.
when it comes in the json file has alot of values and properties in it.
i add about 5-6 properties to it myself for manipulation in my software. When I am all done with my software here I want to serialize this datatable back to json. but with the added properties.
problem is I finally figured out how to serialize my properties back to the file, and realized that in the process I dont serialize all the other fields back in it seems. there are dozens of them and they are nested. I'm not to sure how to get all the nested info into a datatable.
can anyone explain or help me pack all this info into my datatable?
below will be some code snips to show my process so far.
Here is main event
this is where I deserialize the file and load to datagridview.
public void MainForm_Load(object sender, EventArgs e)
{
var loadscreen = new SplashScreen();
loadscreen.Show();
//double buffer fixes latency when scrolling thru datagridviews
toolDataGridView.GetType().GetProperty("DoubleBuffered",
System.Reflection.BindingFlags.Instance |
BindingFlags.NonPublic).SetValue(toolDataGridView, true,
null);
//json file holding all data to be parsed for tool list.
string myDynamicJSON = File.ReadAllText(#"testLibrary.json");
//object with json data in it
ToolJson ToolData = JsonConvert.DeserializeObject<ToolJson>(myDynamicJSON);
//DataTable with something in it, do the binding
BindingSource SBind = new BindingSource
{
DataSource = tooldataSet.Tables["Tool"]
};
//looks into File finds json fields, and assign them to variables to be used in C# to
create the rows.
foreach (var datum in ToolData.datum)
{
string description = datum.Description;
string vendor = datum.Vendor;
double cost = datum.Cost;
string serial = datum.ProductLink;
string employee = datum.employee;
string location = datum.location;
bool returntool = datum.returnTool;
int onHand = datum.onHandQty;
int stockQty = datum.stockQty;
int orderQty = ToolData.Order(datum.stockQty, datum.onHandQty); //stockQty -
onHand = orderQty, if value is less than 0, set the value of orderQty to 0.
string toolType = datum.Type;
double diameter = datum.Geometry.Dc;
double OAL = datum.Geometry.Oal;
string productID = datum.ProductId;
//Populate the DataTable with rows of data
DataRow dr = tooldataSet.Tool.NewRow();
// Fill the values
dr["Description"] = description;
dr["Vendor"] = vendor;
dr["Cost"] = cost;
dr["Serial #"] = serial;
dr["Employee"] = employee;
dr["Location"] = location;
dr["OnHand"] = onHand;
dr["StockQty"] = stockQty;
dr["OrderQty"] = orderQty;
dr["Return"] = returntool;
dr["Diameter"] = diameter;
dr["OAL"] = OAL;
dr["Type"] = toolType;
dr["Product Id"] = productID;
//once all data is added to the row, add the row, and loop untill all data is
loaded.
tooldataSet.Tool.Rows.Add(dr);
}
toolDataGridView.RowHeadersWidthSizeMode =
DataGridViewRowHeadersWidthSizeMode.DisableResizing;
toolDataGridView.RowHeadersVisible = false;
//bind our dataset.table to the gridview
toolDataGridView.DataSource = SBind;
toolDataGridView.RowHeadersWidthSizeMode =
DataGridViewRowHeadersWidthSizeMode.EnableResizing;
toolDataGridView.RowHeadersVisible = true;
//fills drop down employee list with names from the text file
PopulateList(#"EmployeeList.txt");
//hide splashscreen once Gridview has loaded the data
loadscreen.Hide();
}
Here is simple button click event to trigger the serializing back to the file
private void button1_Click(object sender, EventArgs e)
{
BindingSource SBind = new BindingSource
{
DataSource = tooldataSet.Tables["Tool"]
};
toolDataGridView.DataSource = SBind;
var serialized = Newtonsoft.Json.JsonConvert.SerializeObject(tooldataSet.Tool,
Formatting.Indented);
System.IO.File.WriteAllText(#"testLibrary.json", serialized);
}
And finally here is a snippet of the json file, this is only 1 item in the list of hundreds
{
"data": [
{
"BMC": "carbide",
"Cost": 52.68,
"Employee": "",
"GRADE": "Mill Generic",
"Location": "",
"description": "5/8-11\"",
"geometry": {
"CSP": false,
"DC": 0.433,
"HAND": true,
"LB": 2,
"LCF": 0.5,
"NOF": 4,
"NT": 1,
"OAL": 5,
"SFDM": 0.625,
"TP": 0.0909091,
"shoulder-length": 1.969,
"thread-profile-angle": 60
},
"guid": "0112c196-8a79-421d-8dda-d4aa964aa6d7",
"holder": {
"description": "Maritool CAT40-ER32-2.35",
"guid": "e800051b-e2d6-4699-a2b6-dad6466a0a0c",
"last_modified": 1485790626152,
"product-id": "CAT40-ER32-2.35",
"product-link": "",
"segments": [
{
"height": 0.148,
"lower-diameter": 1.5,
"upper-diameter": 1.97
},
{
"height": 0.836,
"lower-diameter": 1.97,
"upper-diameter": 1.97
}
],
"type": "holder",
"unit": "inches",
"vendor": "Maritool"
},
"onHandQty": 3,
"post-process": {
"break-control": false,
"comment": "",
"diameter-offset": 17,
"length-offset": 17,
"live": true,
"manual-tool-change": false,
"number": 17,
"turret": 0
},
"product-id": "GMDTTM58-11UN4FL",
"product-link": "6010",
"start-values": {
"presets": [
{
"description": "",
"f_n": 0.012091641057817,
"f_z": 0.0031,
"guid": "b118ce46-da35-4ed6-9806-b98e05ffe077",
"n": 2646.45632854884,
"n_ramp": 2646,
"name": "Tool Steel",
"tool-coolant": "flood",
"use-stepdown": false,
"use-stepover": false,
"v_c": 300,
"v_f": 32.8160584740056,
"v_f_leadIn": 32,
"v_f_leadOut": 32,
"v_f_plunge": 32,
"v_f_ramp": 32
},
{
"description": "",
"f_n": 0.01118476797848,
"f_z": 0.0028,
"guid": "0e1767f5-b0ef-422f-b49d-6cb8c3eb06ed",
"n": 3308.0704106860494,
"n_ramp": 3308,
"name": "Stainless Steel",
"tool-coolant": "flood",
"use-stepdown": false,
"use-stepover": false,
"v_c": 375,
"v_f": 37.0503885996837,
"v_f_leadIn": 37,
"v_f_leadOut": 37,
"v_f_plunge": 37,
"v_f_ramp": 37
}
]
},
"stockQty": 5,
"type": "thread mill",
"unit": "inches",
"vendor": "Gorilla Mill"
}
]
}
EDIT
Figured I should add in what my result is right now if I click m button
[
{
"Description": "5/8-11\"",
"Cost": 0.0,
"Vendor Item Number": null,
"Vendor Item": null,
"Serial #": "6010",
"Source": null,
"Description3": null,
"Description2": null,
"LastInventory": null,
"Last Price": null,
"DC": "0.433",
"OAL": "5",
"GUID": "0112c196-8a79-421d-8dda-d4aa964aa6d7",
"Product Id": null,
"Type": "thread mill",
"OnHandQty": 0,
"StockQty": 0,
"OrderQty": 0,
"Return": false,
"Employee": "",
"Vendor": "Gorilla Mill",
"Location": "",
"Grade": "Mill Generic",
"BMC": "Carbide",
"start-values": "QuickType.StartValues",
"unit": "Inches",
"geometry": "QuickType.Geometry",
"CSP": "False",
"HAND": "True",
"LB": "2",
"LCF": "0.5",
"NOF": "4",
"NT": "1",
"SFDM": "0.625",
"TP": "0",
"shoulder-length": "1.969",
"thread-profile-angle": "60",
"SIG": "0",
"RE": "0",
"TA": "0",
"tip-diameter": "0",
"tip-length": "0",
"break-control": "False",
"comment": "",
"diameter offset": "17",
"length offset": "17",
"live": "True",
"manual tool change": "False",
"number": "17",
"turret": "0",
"presets": "QuickType.Preset[]",
"holder": "QuickType.Holder",
"post-process": "QuickType.PostProcess",
"Diameter": null,
"last_modified": null,
"product-id": "GMDTTM58-11UN4FL",
"product-link": null,
"segments": null
}
]
Also to note I got my class using quicktype.io online, so the class can handle the entire file no problem(I would assume)
EDIT AGAIN
namespace QuickType
{
using System;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
public class ToolJson
{
[JsonProperty("data")]
public List<Datum> datum { get; set; }
[JsonProperty("version")]
public long Version { get; set; }
public int Order(int stockQty, int onHandQty)
{
int orderQty = stockQty - onHandQty;
if (orderQty < 0)
{
orderQty = 0;
}
return orderQty;
}
}
public partial class Datum
{
[JsonProperty("BMC")]
public Bmc Bmc { get; set; }
[JsonProperty("description")]
public string Description { get; set; }
[JsonProperty("GRADE")]
public string Grade { get; set; }
[JsonProperty("geometry")]
public Geometry Geometry { get; set; }
[JsonProperty("guid")]
public string Guid { get; set; }
[JsonProperty("holder")]
public Holder holder { get; set; }
[JsonProperty("post-process")]
public PostProcess PostProcess { get; set; }
[JsonProperty("product-id")]
public string ProductId { get; set; }
[JsonProperty("product-link")]
public string ProductLink { get; set; }
[JsonProperty("start-values")]
public StartValues StartValues { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("unit")]
public Unit Unit { get; set; }
[JsonProperty("vendor")]
public string Vendor { get; set; }
[JsonProperty("Cost")]
public double Cost { get; set; }
[JsonProperty("Employee")]
public string employee { get; set; }
[JsonProperty("Location")]
public string location { get; set; }
[JsonProperty("onHandQty")]
public int onHandQty { get; set; }
[JsonProperty("stockQty")]
public int stockQty { get; set; }
[JsonProperty("orderQty")]
public int orderQty { get; set; }
[JsonProperty("ReturnTool")]
public bool returnTool { get; set; }
}
public partial class Geometry
{
[JsonProperty("CSP")]
public bool Csp { get; set; }
[JsonProperty("DC")]
public double Dc { get; set; }
[JsonProperty("HAND")]
public bool Hand { get; set; }
[JsonProperty("LB")]
public double Lb { get; set; }
[JsonProperty("LCF")]
public double Lcf { get; set; }
[JsonProperty("NOF")]
public long Nof { get; set; }
[JsonProperty("NT")]
public long Nt { get; set; }
[JsonProperty("OAL")]
public double Oal { get; set; }
[JsonProperty("SFDM")]
public double Sfdm { get; set; }
[JsonProperty("TP")]
public double Tp { get; set; }
[JsonProperty("shoulder-length")]
public double ShoulderLength { get; set; }
[JsonProperty("thread-profile-angle")]
public long ThreadProfileAngle { get; set; }
[JsonProperty("SIG")]
public long Sig { get; set; }
[JsonProperty("RE")]
public double Re { get; set; }
[JsonProperty("TA")]
public long Ta { get; set; }
[JsonProperty("tip-diameter")]
public double TipDiameter { get; set; }
[JsonProperty("tip-length")]
public double TipLength { get; set; }
}
public partial class Holder
{
[JsonProperty("description")]
public string Description { get; set; }
[JsonProperty("guid")]
public string Guid { get; set; }
[JsonProperty("last_modified")]
public string LastModified { get; set; }
[JsonProperty("product-id")]
public string ProductId { get; set; }
[JsonProperty("product-link")]
public string ProductLink { get; set; }
[JsonProperty("segments")]
public Segment[] Segments { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("unit")]
public string Unit { get; set; }
[JsonProperty("vendor")]
public string Vendor { get; set; }
}
public partial class Segment
{
[JsonProperty("height")]
public double Height { get; set; }
[JsonProperty("lower-diameter")]
public double LowerDiameter { get; set; }
[JsonProperty("upper-diameter")]
public double UpperDiameter { get; set; }
}
public partial class PostProcess
{
[JsonProperty("break-control")]
public bool BreakControl { get; set; }
[JsonProperty("comment")]
public string Comment { get; set; }
[JsonProperty("diameter-offset")]
public long DiameterOffset { get; set; }
[JsonProperty("length-offset")]
public long LengthOffset { get; set; }
[JsonProperty("live")]
public bool Live { get; set; }
[JsonProperty("manual-tool-change")]
public bool ManualToolChange { get; set; }
[JsonProperty("number")]
public long Number { get; set; }
[JsonProperty("turret")]
public long Turret { get; set; }
}
public partial class StartValues
{
[JsonProperty("presets")]
public Preset[] Presets { get; set; }
}
public partial class Preset
{
[JsonProperty("description")]
public string Description { get; set; }
[JsonProperty("f_n")]
public double? FN { get; set; }
[JsonProperty("f_z")]
public double? FZ { get; set; }
[JsonProperty("guid")]
public Guid Guid { get; set; }
[JsonProperty("n")]
public double N { get; set; }
[JsonProperty("n_ramp")]
public double? NRamp { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("tool-coolant")]
public ToolCoolant ToolCoolant { get; set; }
[JsonProperty("use-stepdown")]
public bool UseStepdown { get; set; }
[JsonProperty("use-stepover")]
public bool UseStepover { get; set; }
[JsonProperty("v_c")]
public double VC { get; set; }
[JsonProperty("v_f")]
public double? VF { get; set; }
[JsonProperty("v_f_leadIn")]
public double? VFLeadIn { get; set; }
[JsonProperty("v_f_leadOut")]
public double VFLeadOut { get; set; }
[JsonProperty("v_f_plunge")]
public double VFPlunge { get; set; }
[JsonProperty("v_f_ramp")]
public double VFRamp { get; set; }
[JsonProperty("v_f_retract")]
public double VFRetract { get; set; }
[JsonProperty("stepdown")]
public double Stepdown { get; set; }
[JsonProperty("stepover")]
public double Stepover { get; set; }
}
public enum Bmc { Carbide, Hss };
public enum Grade { Generic, MillGeneric };
public enum Description { LongHolder, MaritoolCat40Er32235 };
public enum ProductId { Cat40Er32235, Empty };
public enum TypeEnum { Holder };
public enum Unit { Inches, Millimeters };
public enum Vendor { Empty, Maritool };
public enum ToolCoolant { Disabled, Flood };
Latest Edit
the following code will deser and then set the object to the DGV. other than this small bit of code there isn't much else I have to load the content.
var v = JsonConvert.DeserializeObject<ToolJson>
(File.ReadAllText(#"testLibrary.json"));
//set DGV source to our datums
toolDataGridView.DataSource = v.Datums.Cast<IInteresting>
().ToList();
Newest Edit
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft;
using Newtonsoft.Json;
namespace QuickType
{
public interface IInteresting
{
//adding below creates the columns for our DGV
string ProductLink {get;set;}
string Type { get; set; }
string Description { get; set; }
string Vendor { get; set; }
double GeometryDc { get; set; }
double GeometryOal { get; set; }
double Cost { get; set; }
int onHandQty { get; set; }
int OrderQty { get; set; }
int stockQty { get; set; }
string location { get; set; }
string employee { get; set; }
}
public partial class Datum : IInteresting
{
//top level props in datum
public int OrderQty { get; set; }
[JsonProperty("product-link")]
public string ProductLink { get; set; }
[JsonProperty("Cost")]
public double Cost { get; set; }
[JsonProperty("Employee")]
public string employee { get; set; }
[JsonProperty("Location")]
public string location { get; set; }
[JsonProperty("onHandQty")]
public int onHandQty { get; set; }
[JsonProperty("stockQty")]
public int stockQty { get; set; }
[JsonProperty("orderQty")]
public int orderQty { get; set; }
[JsonProperty("ReturnTool")]
public bool returnTool { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("vendor")]
public string Vendor { get; set; }
[JsonProperty("product-id")]
public string ProductId { get; set; }
[JsonProperty("description")]
public string Description { get; set; }
//below are the props that are nested, we need to pull them out of
the nest
[JsonIgnore]
public double GeometryDc
{
get => this.Geometry.Dc;
set => this.Geometry.Dc = value;
}
[JsonIgnore]
public double GeometryOal
{
get => this.Geometry.Oal;
set => this.Geometry.Oal = value;
}
}
}
Edit including Serialization
the button click event below, should simulate what should happen when the user closes the form. button click instead for testing.
what happens is it serializes, but its not in the correct format.
private void button2_Click(object sender, EventArgs e)
{
File.WriteAllText(#"C:\Users\User\OneDrive - Motion
Controls Robotics, Inc\Desktop\test
inventory\testLibrary1.json",
JsonConvert.SerializeObject(toolDataGridView.DataSource,
Formatting.Indented));
}
Add this somewhere, in another class:
public interface IInteresting
{
string Description { get; set; }
double GeometryDc { get; set; }
double GeometryOal { get; set; }
}
public partial class Datum : IInteresting
{
[JsonIgnore]
public double GeometryDc {
get => this.Geometry.Dc;
set => this.Geometry.Dc = value;
}
[JsonIgnore]
public double GeometryOal
{
get => this.Geometry.Oal;
set => this.Geometry.Oal = value;
}
}
This is just a fragment; you can fill in the other props later. I have deomnstrated an interface that has 3 props. One is a straight up a property of Datum already (Description). The other two are props that dig out nested data; they need implementing, like I showed, including the JsonIgnore tag. Your remaining props are likely to be similar to either the first case (already a prop of Datum, just needs mentioning in interface) or a nested data (needs a new name inventing in interface and a new code putting to dig it out of the hierarchy)
Then put this code behind in a new form called Form1 that contain a DataGridView1 and a Button1 (in the designer):
public Form1(string s1 = null)
{
InitializeComponent();
var v = JsonConvert.DeserializeObject<ToolJson>(File.ReadAllText("textfile1.json"));
//note I renamed your `datum` property to `Datums`
dataGridView1.DataSource = v.Datums.Cast<IInteresting>().ToList();
}
private void button1_Click(object sender, EventArgs e)
{
var x = JsonConvert.SerializeObject(dataGridView1.DataSource);
} //put a breakpoint on this line
The datagridview gets a list of IInteresting, and it only makes columns for props on an IInteresting, so in this case I see 3 columns (3 props):
Edit some data
Click the button. The datasource of the grid (it contains all the data, not just the visible ones) is serialized and the output contains all the data
Adding new data, not already present in the json:
public interface IInteresting
{
string Description { get; set; }
double GeometryDc { get; set; }
double GeometryOal { get; set; }
string DatumXxNew {get; set;}
string GeometryXxNew {get; set;}
}
public partial class Datum : IInteresting
{
[JsonIgnore]
public double GeometryDc {
get => this.Geometry.Dc;
set => this.Geometry.Dc = value;
}
[JsonIgnore]
public double GeometryOal
{
get => this.Geometry.Oal;
set => this.Geometry.Oal = value;
}
//do not JsonIgnore
public string DatumXxNew {get; set;}
//DO JsonIgnore this one, but NOT the one it links to
[JsonIgnore]
public string GeometryXxNew {
get => this.Geometry.XxNew;
set => this.Geometry.XxNew = value;
}
}
public partial class Geometry{
//do not JsonIgnore
public string XxNew {get;set;}
}

Correct an invalid Json string and convert it to C# Class

I want to convert the following json string to a C# class. But i cant figure it out... even with a online converter programm like "json2csharp".
{[
{
"tmcp_post_fields": [],
"product_id": 703,
"per_product_pricing": true,
"cpf_product_price": "45",
"variation_id": false,
"form_prefix": "",
"tc_added_in_currency": "EUR",
"tc_default_currency": "EUR"
}
]}
Can someone help me?
I tried these false variations:
public class myclass
{
public List<object> tmcp_post_fields { get; set; }
public int product_id { get; set; }
public bool per_product_pricing { get; set; }
public string cpf_product_price { get; set; }
public bool variation_id { get; set; }
public string form_prefix { get; set; }
public string tc_added_in_currency { get; set; }
public string tc_default_currency { get; set; }
}
or a List of this class
List<myclass>
I use this code to convert it
if (value != null && value.GetType().FullName.StartsWith("Newtonsoft.Json"))
{
string s = value.GetType().FullName;
if (value.GetType().FullName.EndsWith("JArray"))
{
JArray ja = (JArray)Convert.ChangeType(value, typeof(JArray));
if (ja.HasValues)
{
try
{
return ja.ToObject<myclass>(); //this
return ja.ToObject<List<myclass>>(); //or this does NOT work for me
}
catch { }
return value;
}
else
return null;
}
I allway got this error:
Newtonsoft.Json.JsonReaderException - Error reading string. Unexpected
token
If I remove the first opening and closing {} it would work.
your json is not valid, it has extra {} on the sides. Try this
var json=...your json
json=json.Substring(1,json.Length-2);
var jsonDeserialized = JsonConvert.DeserializeObject<Data[]>(json);
and class
public class Data
{
public List<object> tmcp_post_fields { get; set; }
public int product_id { get; set; }
public bool per_product_pricing { get; set; }
public string cpf_product_price { get; set; }
public bool variation_id { get; set; }
public string form_prefix { get; set; }
public string tc_added_in_currency { get; set; }
public string tc_default_currency { get; set; }
}
Another option is to use insert string. This option is even better since you can use parse json string as well.
json=json.Insert(1,"result:");
var jsonDeserialized = JsonConvert.DeserializeObject<Root>(json);
and class
public class Root
{
public Data[] result {get; set;}
}
output
{
"result": [
{
"tmcp_post_fields": [],
"product_id": 703,
"per_product_pricing": true,
"cpf_product_price": "45",
"variation_id": false,
"form_prefix": "",
"tc_added_in_currency": "EUR",
"tc_default_currency": "EUR"
}
]
}

Blazor Json to class conversion failure

I have built a service that is retrieving a sample file.
return await _httpClient.GetFromJsonAsync<BitcoinDetails>("https://localhost:44356/sample-data/jsonresult.json");
Example
"id": 1,
"name": "Bitcoin",
"symbol": "BTC",
"slug": "bitcoin",
"num_market_pairs": 9550,
"date_added": "2013-04-28T00:00:00.000Z",
"tags": [
"mineable",
"pow",
"sha-256",
"store-of-value",
"state-channels"
],
"max_supply": 21000000, -- or null if not set
"circulating_supply": 18555956,
"total_supply": 18555956,
"platform": null,
"cmc_rank": 1,
"last_updated": "2020-11-27T21:22:02.000Z",
"quote": {
"USD": {
"price": 17069.598651577406,
"volume_24h": 38571181876.87967,
"percent_change_1h": 1.46329039,
"percent_change_24h": 0.92405679,
"percent_change_7d": -8.25816318,
"market_cap": 316742721516.32965,
"last_updated": "2020-11-27T21:22:02.000Z"
}
}
}
Now I have a class that has the following properties
public class Datum
{
public int id { get; set; }
public string name { get; set; }
public string symbol { get; set; }
public string slug { get; set; }
public int num_market_pairs { get; set; }
public DateTime date_added { get; set; }
public List<string> tags { get; set; }
public long? max_supply { get; set; }
public double circulating_supply { get; set; }
public double total_supply { get; set; }
public Platform platform { get; set; }
public int cmc_rank { get; set; }
public DateTime last_updated { get; set; }
public Quote quote { get; set; }
}
Keeping in mind that there are many more records I am getting the following error
Unhandled exception rendering component: The JSON value could not be converted to System.Nullable`1[System.Int64]. Path: $.data[80].max_supply |
make dto nullable and then try as follows:
var response = client.GetAsync(apiUrl);
if (response.Result.IsSuccessStatusCode)
{
var data = response.Result.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<Datum>(data.Result);
return result;
}
I ended up using a proxy call however this code did work:
var response = await _httpClient.GetAsync("https://localhost:5001/proxy");
if (response.IsSuccessStatusCode)
{
var data = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<BitcoinDetails>(data);
return result;
}
else
{
throw new Exception("Failed to get data");
}
and added this to the class property
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]

JSON object throws up null response but it isn't null

Tried to parse JSON object using JavaScriptSerializer().Deserialize but getting thrown a null error at foreach (var item in getRoute.results) where Route getRoute = new JavaScriptSerializer().Deserialize<Route>(strresulttest);
The thing is, when I debugged strresulttest by printing out its contents, I was able to see my expected JSON output as shown here https://codeshare.io/5vM6X4
Code to parse JSON:
public class Route
{
public List<GetRoute> results { get; set; }
}
public class GetRoute
{
public string status_message { get; set; }
public string viaRoute { get; set; }
public string subtitle { get; set; }
public int totalTime { get; set; }
public int totalDistance { get; set; }
}
private void GetInstructions()
{
//GET METHOD for route query
string strurltest = String.Format("https://developers.onemap.sg/privateapi/routingsvc/route?start="+
startLat+","+ startLon +"&end="+ destinationLat +","+ destinationLon+"&"+
"routeType="+ transportType + "&token="+token);
WebRequest requestObjGet = WebRequest.Create(strurltest);
requestObjGet.Method = "GET";
HttpWebResponse responseObjGet = null;
responseObjGet = (HttpWebResponse)requestObjGet.GetResponse();
string strresulttest = null;
using (Stream stream = responseObjGet.GetResponseStream())
{
StreamReader sr = new StreamReader(stream);
strresulttest = sr.ReadToEnd();
//reminder: remove after prod. GET is working.
System.Diagnostics.Debug.WriteLine(strresulttest);
sr.Close();
}
//display search recommendations
Route getRoute = new JavaScriptSerializer().Deserialize<Route>(strresulttest);
foreach (var item in getRoute.results)
{
//reminder: remove after prod.
System.Diagnostics.Debug.WriteLine("Route via: " + item.viaRoute + "\n");
System.Diagnostics.Debug.WriteLine("Description: " + item.subtitle + "\n");
}
}
Expected JSON output (shown when System.Diagnostics.Debug.WriteLine(strresulttest);):
{
"status_message": "Found route between points",
"route_geometry": "m{`G_cyxRaAmALMtAyAj#g#RIZG|#KTC??RCxBQ\\KAOa#sDAQWwBM_AUmBEa#Ky#_#kDKoAIgAAs#Ce#?M|#_#PINUFk#Ik#e#aCu#wBeBoD_A}AmBqC{#iA_AeAyAqA{LmKmAu#k#g#y#Jk#r#k#r#GP#PFJhAt#oEnGw#i#QTMPs#g#}AzBr#d#JQ",
"status": 0,
"route_instructions": [
[
"Head",
"SINARAN DRIVE",
56,
"1.320394,103.844478",
18,
"56m",
"North East",
"North",
"driving",
"Head Northeast On Sinaran Drive"
],
[
...
],
...
],
"route_name": [
"MOULMEIN ROAD",
"WHAMPOA ROAD"
],
"route_summary": {
"start_point": "SINARAN DRIVE",
"end_point": "WHAMPOA ROAD",
"total_time": 390,
"total_distance": 2675
},
"viaRoute": "JALAN BAHAGIA",
"subtitle": "Fastest route, assuming usual traffic",
"phyroute": {
"status_message": "Found route between points",
"route_geometry": "m{`G_cyxRaAmALMtAyAj#g#RIZG|#KTC??Ao#BcB?kCBIHK|Ay#M_AUmBEa#Ky#_#kDKoAIgAAs#Ce#?M?OBw#BsCEq#Q{#Qm#KQGMaCNM#iFXO?sCNo#LCa#QaICe#EI?EBQTi#Ha##c#CMGWOYOOgEgD{BeBuB}AoEnGw#i#QTMPs#g#}AzBr#d#JQ",
"status": 0,
"route_instructions": [
[
"Head",
"SINARAN DRIVE",
56,
"1.320394,103.844478",
18,
"56m",
"North East",
"North",
"driving",
"Head Northeast On Sinaran Drive"
],
[
...
],
...
],
"route_name": [
...
],
"route_summary": {
...
},
"viaRoute": "BALESTIER ROAD",
"subtitle": "Shortest distance"
}
}
You are getting a null in results because the class structure that you are deserializing into does not match your JSON. The JSON you linked in your question corresponds to this class structure instead:
public class Route
{
public string status_message { get; set; }
public string route_geometry { get; set; }
public int status { get; set; }
public List<List<object>> route_instructions { get; set; }
public List<string> route_name { get; set; }
public RouteSummary route_summary { get; set; }
public string viaRoute { get; set; }
public string subtitle { get; set; }
public Phyroute phyroute { get; set; }
}
public class RouteSummary
{
public string start_point { get; set; }
public string end_point { get; set; }
public int total_time { get; set; }
public int total_distance { get; set; }
}
public class Phyroute
{
public string status_message { get; set; }
public string route_geometry { get; set; }
public int status { get; set; }
public List<List<object>> route_instructions { get; set; }
public List<string> route_name { get; set; }
public RouteSummary route_summary { get; set; }
public string viaRoute { get; set; }
public string subtitle { get; set; }
}
You can deserialize and get the viaRoute and subtitle like this:
Route route = new JavaScriptSerializer().Deserialize<Route>(strresulttest);
System.Diagnostics.Debug.WriteLine("Route via: " + route.viaRoute);
System.Diagnostics.Debug.WriteLine("Description: " + route.subtitle);

Change existing JSON message format into new with fields in C#?

We have to do some changes in existing JSON response and it requires to modify existing c# code too. Till now I've tried but don't get the exact idea about the formatting as it is new for me.
Can any one please check and suggest the changes in below code?
Existing JSON message:
"hotel_room_types": {
"QUEEN": {
"code": "QUEEN",
"bed_type": {
"standard": [
5
],
"custom": []
},
"extra_bed_type": {
"standard": [
5
],
"custom": []
},
"accessibility": "compliant_with_local_laws_for_disabled",
"room_smoking_policy": "non_smoking"
}
}
In above JSON message we have to replace the "bed_type" and "extra_bed_type" with "bed_configurations" and "extra_bed_configurations" in below newly provided format by client:
"hotel_room_types": {
"QUEEN": {
"code": "QUEEN",
"bed_configurations": [
[{
"type": "standard",
"code": 3,
"count": 1
}],
[{
"type": "standard",
"code": 1,
"count": 2
}]
],
"extra_bed_configurations": [
[{
"type": "standard",
"code": 900302,
"count": 1
},
{
"type": "custom",
"name": "Rollaway with wheel locks and adjustable height",
"count": 1
}]
],
"accessibility": "compliant_with_local_laws_for_disabled",
"room_smoking_policy": "non_smoking"
}
}
Existing C# code to generate the JSON response message format:
public class HotelRoomType
{
public string code { get; set; }
public string name { get; set; }
public string description { get; set; }
public List<Photo> photos { get; set; }
public Amenities room_amenities { get; set; }
public string room_size { get; set; }
public string room_size_units { get; set; }
public BedType bed_type { get; set; }
public BedType extra_bed_type { get; set; }
public RoomViewType room_view_type { get; set; }
public string accessibility { get; set; }
public MaxOccupancy max_occupancy { get; set; }
public string room_smoking_policy { get; set; }
}
Below is the code to fill the data in required fields of JSON message its inside a method which contains lines of code so I get it separately:
HotelRoomType hotelrmtype = new HotelRoomType();
hotelrmtype.bed_type = Common.GetStandardBedTypeMappingID(rm.BedType);
if (rm.NumOfBed > 1)
hotelrmtype.extra_bed_type = hotelrmtype.bed_type; //same as bed type
hotelrmtypeDict.Add(rm.Code, hotelrmtype); //Binding Data into Dictionary.
GetStandardBedTypeMappingID() contains :
public static CRS.TripConnect.BedType GetStandardBedTypeMappingID(short code)
{
CRS.TripConnect.BedType tripConnectBedType = new CRS.TripConnect.BedType();
List<int> standardBedTypes = new List<int>();
List<object> customBedTypes = new List<object>();
tripConnectBedType.standard = standardBedTypes;
tripConnectBedType.custom = customBedTypes; //These is blank.
short id = 0;
switch (code)
{
case 10:
id = 3;
break;
case 20: // 20 Queen Q 5
id = 5;
break;
case 30: // 30 Double D 1
id = 1;
break;
case 40: // 40 Twin T 8
id = 8;
break;
}
standardBedTypes.Add(id);
return tripConnectBedType;
}
Update: With the help of #Sam Answer below I have modified the code:
public class HotelRoomType
{
//Added following properties
public List<List<Bed_Configurations>> bed_configurations { get; set; }
public List<List<Extra_Bed_Configurations>> extra_bed_configurations { get; set; }
}
Created two new classes as:
public class Bed_Configurations
{
public string type { get; set; }
public int code { get; set; }
public int count { get; set; }
}
public class Extra_Bed_Configurations
{
public string type { get; set; }
public int code { get; set; }
public int count { get; set; }
public string name { get; set; }
}
Now the question is: How to fill these two list?
I'm trying to achieve this like below but it is giving me conversion error.
Bed_Configurations bdConfig = new Bed_Configurations();
bdConfig.type = "Standard";
bdConfig.code = Common.GetStandardBedTypeMappingIDnew(rm.BedType);
bdConfig.count = rm.NumOfBed;
hotelrmtype.bed_configurations.Add(bdConfig);
Error Message:
Please Advise the changes in the above code so as to get the required JSON message. Appreciate your help!
public class RootClass
{
public HotelRoomType hotel_room_types { get; set; }
}
public class HotelRoomType
{
public BedModelAndDetails QUEEN { get;set; }
}
public class BedModelAndDetails
{
public string accessibility { get; set; }
public string room_smoking_policy { get; set; }
public string code { get; set; }
//public BedType bed_type { get; set; }
public object bed_type { get; set; }
//public BedType extra_bed_type { get; set; }
public object extra_bed_type { get; set; }
public List<List<BedConfiguration>> bed_configurations { get; set; }
public List<List<BedConfiguration>> extra_bed_configurations { get; set; }
}
public class BedType
{
public List<int> standard { get; set; }
public List<int> custom { get; set; }
}
public class BedConfiguration
{
public string type { get; set; }
public int code { get; set; }
public int count { get; set; }
}
[TestMethod]
public void ReplaceJson()
{
var inputJson1 = "{\"hotel_room_types\": {\"QUEEN\": {\"code\": \"QUEEN\", \"bed_type\": {\"standard\": [5],\"custom\": [] }, \"extra_bed_type\": { \"standard\": [5], \"custom\": [] },\"accessibility\": \"compliant_with_local_laws_for_disabled\", \"room_smoking_policy\": \"non_smoking\" } " +"}}";
var input1 = JsonConvert.DeserializeObject<RootClass>(inputJson1, new JsonSerializerSettings {NullValueHandling = NullValueHandling.Ignore});
var inputJson2 = "{\"hotel_room_types\": {\"QUEEN\": {\"code\": \"QUEEN\",\"bed_configurations\": [[{\"type\": \"standard\",\"code\": 3,\"count\": 1}],[{\"type\": \"standard\",\"code\": 1,\"count\": 2}]],\"extra_bed_configurations\": [[{\"type\": \"standard\",\"code\": 900302,\"count\": 1},{\"type\": \"custom\",\"name\": \"Rollaway with wheel locks and adjustable height\",\"count\": 1}]],\"accessibility\": \"compliant_with_local_laws_for_disabled\",\"room_smoking_policy\": \"non_smoking\"} }}";
var input2 = JsonConvert.DeserializeObject<RootClass>(inputJson2);
//var finalInput = new RootClass();
//finalInput.hotel_room_types = inputJson1
//input1.hotel_room_types.QUEEN.bed_configurations = input2.hotel_room_types.QUEEN.bed_configurations;
//input1.hotel_room_types.QUEEN.extra_bed_configurations = input2.hotel_room_types.QUEEN.extra_bed_configurations;
input1.hotel_room_types.QUEEN.bed_type = input2.hotel_room_types.QUEEN.bed_configurations;
input1.hotel_room_types.QUEEN.extra_bed_type = input2.hotel_room_types.QUEEN.extra_bed_configurations;
}
Does this help?

Categories

Resources