JSON.NET Deserializing a JSON into a dictionary comes back as null - c#

I have this JSON:
{
"AAPL": { "price": "131.85000" },
"eur/usd": { "price": "1.06290" },
"msft": { "price": "238.76000" }
}
When I try to deserialize this into a dictionary it comes back as null.
I am using the TwelveDataAPI.
https://twelvedata.com/docs#real-time-price
I have tried creating a simple class that will allow me to deserialize this JSON even if there are different tickers and different amounts of them.
My class:
public class CurrentPriceClass
{
public class Root
{
public Dictionary<string, Price> Prices { get; set; }
}
public class Price
{
public string price { get; set; }
}
}
But when I try to deserialize it, it comes back as null, and I cannot iterate over it:
CurrentPriceClass.Root priceRoot = JsonConvert.DeserializeObject<CurrentPriceClass.Root>(
dataJson);
foreach (KeyValuePair<string, CurrentPriceClass.Price> price in priceRoot.Prices)
{
Console.WriteLine($"{price.Key}: {price.Value.price}");
}
The error I get when iterating is:
Object reference not set to an instance of an object.
When debugging priceRoot is null.
I am assuming that this is a problem with my class.

Deserialize as Dictionary<string, CurrentPriceClass.Price> without needing the root class (CurrentPriceClass).
Dictionary<string, CurrentPriceClass.Price> priceRoot = JsonConvert.DeserializeObject<Dictionary<string, CurrentPriceClass.Price>>(dataJson);
foreach (KeyValuePair<string, CurrentPriceClass.Price> price in priceRoot)
{
Console.WriteLine($"{price.Key}: {price.Value.price}");
}
Demo # .NET Fiddle

Related

C# System.Text.Json consider an empty object an empty array

I'm parsing some JSON data I receive from a server using the built-in System.Text.Json module.
Here's an example class that I would use:
public class Something
{
[JsonPropertyName("items")]
public Item[] Items { get; set; }
}
The JSON data for this is usually received like the following, and it's properly parsed with JsonSerializer.Deserialize<Something>():
{
"items": [ { ... }, { ... }, { ... } ]
}
However, when there's no items, the server instead returns an empty object, which causes an exception because it expected an array.
{
"items": {}
}
Is there any way I could set it so that an empty object would be considered as an empty array? I've seen that you can make a custom JSON converter but I struggled to get it working.
you don't need any fansy custom converters in your case. Just try this
public class Something
{
[JsonPropertyName("items")]
public object _items
{
get
{
return Items;
}
set
{
if (((JsonElement)value).ValueKind.ToString() == "Array")
{
Items = ((JsonElement)value).Deserialize<Item[]>();
}
}
}
[System.Text.Json.Serialization.JsonIgnore]
public Item[] Items { get; set; }
}
and if you don't need to serialize it back, you can even remove _items get at all

Deserialize a generic JSON and use its properties

I need to call an API that returns a JSON that can vary.
Sometimes the response could be something like:
[
{
"name": "value"
}
]
while other times
[
{
"property": "value"
}
]
or even
[
{
"name": "value",
"status": "value",
"count": "value"
}
]
Basically, I need to retrieve all values in this JSON for later use.
I tried
var prova = JsonConvert.DeserializeObject<dynamic>(result);, but I can't access the properties using ["indexName"] because the index can vary depending on some factors. Any ideas?
You can create a POCO that that has all the possible properties if they are finite. Like the following :
public class Result {
public string name { get; set; }
public string property { get; set; }
public string status { get; set; }
public string count{ get; set; }
}
And then you can use: var prova = JsonConvert.DeserializeObject<IEnumerable<Result>>(Result);. I change the deserialization to using an IEnumerable because I see that your JSON is an array.
And then you can check if the values are null before accessing them. Since every Result object will only have the property that was available in JSON as non-null.
Alternatively, you can use a Dictionary<string, string> or Dictionary<string, int> and do the following :
var prova = JsonSerializer.Deserialize<IEnumerable<Dictionary<string, string>>>(result) as List<Dictionary<string, string>>;
and then you can access every object of the list and access the property you want like this or TryGetValue Method for more safety.
Console.WriteLine(prova[0]["name"]);
Assumption:
You're getting an array of objects from the api (that doesn't return null data - re: probably why the structure is "dynamic").
Here's one way:
//System.Text.Json
var foo = JsonSerializer.Deserialize<JsonElement>(array_from_api);
//It's an array (assumption) of one or more objects
foreach (JsonElement element in foo.EnumerateArray())
{
//iterate through each object's properties
foreach (JsonProperty o in element.EnumerateObject())
{
//Assumption: value isn't a nested object/array, otherwise adjust...
Console.WriteLine($"{o.Name} = {o.Value}");
}
}
//Json.Net
//It's an array (assumption) of one or more objects
JArray deserialized = JsonConvert.DeserializeObject<JArray>(array_from_api);
foreach (JObject jo in deserialized)
{
//iterate through each JObject's properties
foreach (JProperty p in jo.Properties())
{
Console.WriteLine($"{p.Name} = {p.Value}");
}
}
Note: If the structure is more complex - more nesting, you'll have to do some checks and adjust accordingly (re: nested arrays, objects, etc)

What is the correct way to parse this JSON object in C#?

This is the JSON object I am receiving from a GET request:
{
"data": {
"valve_maker": [],
"water_volume": [
"15L",
"20L",
"..."
],
"cylinder_manufacturer": [
"Tianhai"
],
"qc_stamp": [
"TS"
],
"reference_standard": [
"GB 5099"
],
"production_licence": [
"TS2210752-2016"
],
"valve_production_licence": [
"TSF210030"
],
"rate_of_residual_deformation": {
"1": "<3%",
"2": "<10%"
},
"material_number": {
"1": "30CrMo",
"2": "34CrMo4",
"3": "..."
},
"heat_treatment": {
"1": "...",
"2": "..."
},
"drawing_number": {
"1": "...",
"2": "..."
},
"cylinder_thickness": []
}
right now, I am able to parse JSON objects with a simpler structure like :
{
"data": [
{
"gas_id": "ID of the gas",
"gas_name": "Gas name"
}
]
by using something like this:
private void jsonparsegas(string res)
{
JObject par = JObject.Parse(res);
foreach (JToken data in par["data"].Children())
{
string id = data["gas_id"].ToString();
string name = data["gas_name"].ToString();
if (this.cmbCylType.Items.Contains(name) == false)
{
this.cmbCylType.Items.Add(name);
}
}
}
When I try to apply the same thing to the more complicated JSON object, I get an error:
private void jsonparsecoc(string res)
{
//JObject par = JObject.Parse(res);
var jObj = (JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(res);
foreach (var child in jObj["data"].Children())
{
string vMaker = child["valve_maker"].ToString(); //error thrown here right away
string wVolume = child["water_volume"].ToString();
string cMan = child["cylinder_manufacturer"].ToString();
string QC = child["qc_stamp"].ToString();
string rStandard = child["reference_standard"].ToString();
string pLicence = child["production_licence"].ToString();
string VPL = child["valve_production_licence"].ToString();
string rrd = child["rate_of_residual_deformation"].ToString();
string mNum = child["material_number"].ToString();
string hTreatment = child["heat_treatment"].ToString();
string dNum = child["drawing_number"].ToString();
string cThick = child["cylinder_thickness"].ToString();
}
Cannot access child value on Newtonsoft.Json.Linq.JProperty
I have tried a few different things I found on StackOverflow, but I don't really understand how Deserializing of the objects works. The simpler parsing works just fine, and allows me to add all "gas_name"s that I receive from my GET request to a combobox. The format the first "valve_maker" child of "data" seems to have the same structure as "gas_id" or "gas_name" in the more similar JSON object, but this is where I receive the error right away. If I had to guess at a cause for the error, I'd say it has something to do with the difference between using
"valve_maker": []
and using
"gas_id": "ID of the gas"
in the objects. also I notice "data" is followed by [] brackets in the simpler one, and {} in the more complicated one.
If anyone could link to some good reading material, or offer a good explanation of a solution/what's going on, I'd really appreciate it.
This part is the key to the problem you're having:
in the objects. also I notice "data" is followed by [] brackets in the simpler one, and {} in the more complicated one.
In JSON,
[] brackets enclose an array
{} brackets enclose an object
In both code examples, you are digging into the object by looping through the results using par["data"].Children(). To be consistent with the JSON model, JSON.NET defines different behavior for resolving children of objects and arrays. The children of an object are its properties and the children of an array are its items.
In your code, the input to jsonparsegas is an array of simple objects with 2 properties where the input to jsonparsecoc is a single complex objects with many properties.
In jsonparsegas, the Children() call gives you an array of all the simple gas objects. You loop through these objects and extract the values of "gas_id" and "gas_name" for each object. In your example data, there only happens to be one gas object so your code only executes once.
In jsonparsecoc, the Children() call actually gives you property values for the properties of the complex object, since the result is an object and not an array. So, when you loop through this result you can't access things like "valve_maker", because they are defined on the complex object and you have already stepped into the value for valve_maker then this executes.
The solution is simple. Don't loop through the properties in jsonparsecoc. Instead of foreach(var child in jObj["data"].Children()) you need something like var child = jObj["data"];. This will give you the reference to the object that actually contains each of the properties you are trying to access.
#smartcaveman did a good job of explaining what is going wrong with your code. However, you might find your data a little easier to process if you defined strongly-typed classes for it like this:
class RootObject
{
public Data Data { get; set; }
}
class Data
{
[JsonProperty("valve_maker")]
public List<string> ValveMaker { get; set; }
[JsonProperty("water_volume")]
public List<string> WaterVolume { get; set; }
[JsonProperty("cylinder_manufacturer")]
public List<string> CylinderManufacturer { get; set; }
[JsonProperty("qc_stamp")]
public List<string> QCStamp { get; set; }
[JsonProperty("reference_standard")]
public List<string> ReferenceStandard { get; set; }
[JsonProperty("production_licence")]
public List<string> ProductionLicense { get; set; }
[JsonProperty("valve_production_licence")]
public List<string> ValveProductionLicense { get; set; }
[JsonProperty("rate_of_residual_deformation")]
public Dictionary<string, string> RateOfResidualDeformation { get; set; }
[JsonProperty("material_number")]
public Dictionary<string, string> MaterialNumber { get; set; }
[JsonProperty("heat_treatment")]
public Dictionary<string, string> HeatTreatment { get; set; }
[JsonProperty("drawing_number")]
public Dictionary<string, string> DrawingNumber { get; set; }
[JsonProperty("cylinder_thickness")]
public List<string> CylinderThickness { get; set; }
}
You can deserialize the JSON to your classes like this:
RootObject obj = JsonConvert.DeserializeObject<RootObject>(json);
Demo here: https://dotnetfiddle.net/p0D7ze
public class Test{
public Data data{get;set;}
}
public class Data{
public List<string> Value_maker{get;set;}
public List<String> Water_Volume{get;set;}
public List<String> cylinder_manufacturer{get;set;}
}
Create Class structure Like that and after that use to deserialize
Jsonconvert.DeserializeObject(JsonString)
it will convert json into proper object, keep in mind structure should be proper and property name should be same as your json property
Hope It will Help you

Merge objects to obtain a unique json object in MVC 4

I'm trying to serialize an object in a different way that the default serialization does.
I have a list of objects like this:
public class PausesByAgentModel
{
public PausesByAgentModel()
{
this.Pauses = new Dictionary<string, string>();
}
[DisplayName( "Agent" )]
public string AgentFullName { get; set; }
public Dictionary<string, string> Pauses { get; set; }
}
This object contains the different pauses for a Agent an the time for each pause in a dictionary because the pauses reasons are are dynamics (Key: Pause name, Value: Time in string format).
If I serialize this object as JsonResult to return it in my controller method, I get the following json:
{
"data" : [
{
"AgentFullName" : "John Doe",
[
{ "Break": "00:15:31" },
{ "Launch" : "01:01:23" },
{ "Mail" : "00:05:12" }
]
} ]
}
But I need that the pauses were placed like properties of the same object like this one:
{
"data" : [
{
"AgentFullName" : "John Doe",
"Break": "00:15:31",
"Launch" : "01:01:23",
"Mail" : "00:05:12"
} ]
}
I can't change the class design. So, I need to serialize the object in a different way as default design.
There is a way to merge or serialize the object like the second example?
Thanks.
As #qamar says on the comments, use a dynamic type.
public List<dynamic> ParseData(PausesByAgentModel model){
List<dynamic> result = new List<dynamic>();
foreach(String key in model.Keys){
result.Add(new { pauses = key,value = model[key] });
}
return result;
}

Deserializing a JSON with variable name/value pairs into object in C#

I am using C# .NET 4.0 to parse a JSON into a custom object. I am using JavaScriptSerializer.Deserialize to map it to a class that I wrote. Problem is, the JSON's name/value pairs are not static and vary depending on the argument isChain, as seen in this JSON fragment (better link at bottom):
{
"STATE_WALK_LEFT":{
"isChain":"1",
"x":"1"
},
"STATE_WALK_LEFT_0":{
"x":"0"
},
"STATE_WALK_LEFT_1":{
"x":"40"
},
"STATE_WALK_LEFT_2":{
"x":"80"
},
"STATE_WALK_RIGHT":{
"isChain":"0"
},
"STATE_RUN_LEFT":{
"isChain":"0"
}
}
The chains can have anywhere from _STATE_0 to _STATE_25 entries in the chains. Is there some way to store this data so I don't have to write 12*26 empty classes like so:
public StateWalkLeft0 STATE_WALK_LEFT { get; set; }
public StateWalkLeft0 STATE_WALK_LEFT_0 { get; set; }
public StateWalkLeft1 STATE_WALK_LEFT_1 { get; set; }
public StateWalkLeft2 STATE_WALK_LEFT_2 { get; set; }
public StateWalkLeft3 STATE_WALK_LEFT_3 { get; set; }
Is there a library or some other way I could use to partially parse only the STATE_0, STATE_1, etc fields? Could you maybe suggest a way to add these recently added JSON pairs?
Edited to clarify:
To get an idea of what I'm working with, here is the Class derived from the JSONs:
Check out my full Class to get an idea of what the JSONs contain
Basically, I just need a way to store these recently implemented chains in this class somehow for processing. All of those classes/properties are generated from these JSONs.
Use Newtonsoft Json.NET and as example following code
internal struct ChainX
{
public int x { get; set; }
public int isChain { get; set; }
}
static string json =
#"{
""STATE_WALK_LEFT"":{
""isChain"":""1"",
""x"":""1""
},
""STATE_WALK_LEFT_0"":{
""x"":""0""
},
""STATE_WALK_LEFT_1"":{
""x"":""40""
},
""STATE_WALK_LEFT_2"":{
""x"":""80""
},
""STATE_WALK_RIGHT"":{
""isChain"":""0""
},
""STATE_RUN_LEFT"":{
""isChain"":""0""
}
}";
and a line of code to deserialize to Dictionary:
var values = JsonConvert.DeserializeObject<Dictionary<string, ChainX>>(json);
after that you can simple access values by dictionary key:
ChainX valueWalkLeft1 = values["STATE_WALK_LEFT_1"];

Categories

Resources