How to parse JSON objects with numeric keys using JavaScriptSerializer - c#

I have an object like below to be deserialized in C#. I am wondering how I can parse it. I tried following this example here, but am stumped on how I can get my class to recognize the key of each object (the 2 and the 3 below).
The JSON string below basically represents 2 transactions. I would like to convert each transaction representation into a Transaction object and put it into an array of Transaction object.
{
"2": {
"id": "2",
"user_id": "59",
"offer_id": "1234"
},
"3": {
"id": "3",
"user_id": "59",
"offer_id": "1234"
}
}
Here are my classes:
public class Transactions
{
// what goes here since the "key" field is always different?
}
public class Transaction
{
public int id { get; set; }
public int user_id { get; set; }
public int offer_id { get; set; }
}

It can be done with the JObject in JSON.Net library.
var transactions = JObject.Parse(json).PropertyValues()
.Select(o => o.ToObject<Transaction>());
This should do the trick.

Using the JavaScriptSerializer, you can handle this by deserializing into a Dictionary<string, Transaction>. From there you can convert it to an array pretty easily if you need to.
Example code:
string json = #"
{
""2"": {
""id"": ""2"",
""user_id"": ""59"",
""offer_id"": ""1234""
},
""3"": {
""id"": ""3"",
""user_id"": ""59"",
""offer_id"": ""1234""
}
}";
var serializer = new JavaScriptSerializer();
var dict = serializer.Deserialize<Dictionary<string, Transaction>>(json);
var transactions = dict.Select(kvp => kvp.Value).ToArray();
foreach (Transaction t in transactions)
{
Console.WriteLine(string.Format(
"id: {0}, user_id: {1}, offer_id: {2}", t.id, t.user_id, t.offer_id));
}

I ended up that serializing key-value pairs from Javascript to C# is impossible.
I've changed my code and and made a normal array of objects in JS and sent it to the server.
BUT it is possible to parse a key-value pairs form string variable to Dictionary in C# or to a list of KeyValuePair<x,x>
And it is also possible to build a key-value pair using C# and covert it to JSON or JS

Related

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)

How to parse JSON string for List of List of anonymous object which contains List of objects?

I've been trying to deserialize the following JSON string into a model using Newtonsoft's Json library, but failing to do so. The json string is as follows:-
[
[
{
"events": [
{
"d": "Dec 2019 Final",
"e": "Released 5 Mar 2020"
}
]
}
],
[
{
"events": [
{
"d": "Some String",
"e": "Some Other string"
}
]
}
]
]
I tried doing so by creating its model using Visual Studio internal tool for json to C# (paste special). Also tried creating the models using QuickTypes.io, but so far nothing worked.
The best I can do is parse the api response as List<List<object>> and then manually get the values by iterating its keys & values, which is something I totally want to avoid.
Is there a better way to handle this data?
I hope I understand your question correctly.If you want to stick to Anonymous types, you could make use of JsonConvert.DeserializeAnonymousType for the purpose.
var innerAnonymousType = new {d=string.Empty,e=string.Empty};
var innerAnnonymousTypeList = CreateList(innerAnonymousType);
var outerAnonymousType = CreateList(new {events = innerAnnonymousTypeList});
var result = JsonConvert.DeserializeAnonymousType(json, CreateList(outerAnonymousType));
Where CreateList is defined as
public static List<T> CreateList<T>(params T[] elements)
{
return new List<T>(elements);
}
Using JsonConvert.DeserializeAnonymousType
Output Sample
You can use a base model and parse your json:
public class BaseClass
{
public List<EventModel> Events { get; set; }
}
public class EventModel
{
[JsonProperty(PropertyName = "d")]
public string Date { get; set; }
[JsonProperty(PropertyName = "e")]
public string Event { get; set; }
}
And for deserialize json to model use this:
var model = JsonConvert.DeserializeObject<List<List<BaseClass>>>("your json");

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

Best approach in C# to deserialize json object that can be array or single object [duplicate]

This question already has answers here:
How to handle both a single item and an array for the same property using JSON.net
(9 answers)
Closed 4 years ago.
We're dealing with an json API result. Just to make our lives difficult the provider of the API returns on of the items as an array if there are multiple objects, or as a single object if there is only one.
e.g.
If there is only one object...
{
propertyA: {
first: "A",
second: "B"
}
}
Or if there are multiple:
{
propertyA: [
{
first: "A",
second: "B"
},
{
first: "A",
second: "B"
}
]
}
Does anybody have a good way of dealing with this scenario?
Ideally we'd like to serialize both to
public class ApiResult{
public ApiItem[] PropertyA {get;set;}
}
This works for the second example but of you encounter the first example you get a A first chance exception of type 'System.MissingMethodException' occurred in System.Web.Extensions.dll
Additional information: No parameterless constructor defined for type of 'ApiItem[]'.
I assume the class definition is as below
public class ApiResult
{
public ApiItem[] PropertyA { get; set; }
}
public class ApiItem
{
public string First { get; set; }
public string Second { get; set; }
}
You can deserialize the json into a dynamic variable, then check the type of d.propertyA. If it's JArray then propertyA is an array, so you can deserialize the json into a ApiResult. If it's JObject then propertyA is a single object, so you need to manually construct ApiItem and assign it to PropertyA of ApiResult. Consider the method below
public ApiResult Deserialize(string json)
{
ApiResult result = new ApiResult();
dynamic d = JsonConvert.DeserializeObject(json);
if (d.propertyA.GetType() == typeof (Newtonsoft.Json.Linq.JObject))
{
// propertyA is a single object, construct ApiItem manually
ApiItem item = new ApiItem();
item.First = d.propertyA.first;
item.Second = d.propertyA.second;
// assign item to result.PropertyA[0]
result.PropertyA = new ApiItem[1];
result.PropertyA[0] = item;
}
else if (d.propertyA.GetType() == typeof (Newtonsoft.Json.Linq.JArray))
{
// propertyA is an array, deserialize json into ApiResult
result = JsonConvert.DeserializeObject<ApiResult>(json);
}
return result;
}
The code above will return an instance of ApiResult for both json examples.
Working demo: https://dotnetfiddle.net/wBQKrp
Building upon ekad's answer, I made the code:
Shorter: as now you don't have map one by one every property inside ApiItem
Probably faster in the case of being already an Array (by not calling to both versions of JsonConvert.DeserializeObject with the same input of the json string)
Explicit about how to introduce other properties
Handling the error case of unknown type of our propertyA (the one that can be either an array or an object).
Notice that instead of JsonConvert.DeserializeObject, I call JObject.Parse, and then ToObject<> for only the part I need in that particular case:
static ApiResult Deserialize(string json)
{
JObject j = JObject.Parse(json);
var propA = j["propertyA"];
switch (propA.Type.ToString())
{
case "Object":
return new ApiResult {
PropertyA = new[]{propA.ToObject<ApiItem>()},
SomethingElse = j["somethingElse"].ToObject<string>(),
};
case "Array":
return j.ToObject<ApiResult>();
default:
throw new Exception("Invalid json with propertyA of type " + propA.Type.ToString());
}
}
The API is pretty much the same, but I've added SomethingElse (for showing how other properties can be easily handled with this approach):
public class ApiResult
{
public ApiItem[] PropertyA { get; set; }
public string SomethingElse { get; set; }
}
public class ApiItem
{
public string First { get; set; }
public string Second { get; set; }
}
Working demo: https://dotnetfiddle.net/VLbTMu
JSON# has a very lightweight tool that allows you to achieve this. It will retrieve embedded JSON, regardless of whether or not the embedded JSON is an object, or array, from within larger JSON objects:
const string schoolMetadata = #"{ "school": {...";
var jsonParser = new JsonObjectParser();
using (var stream =
new MemoryStream(Encoding.UTF8.GetBytes(schoolMetadata))) {
Json.Parse(_jsonParser, stream, "teachers");
}
Here we retrieve a "teachers" object from within a larger "school" object.
best way to Serialize/Deserialize to/from JSON is Json.NET
Popular high-performance JSON framework for .NET
Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Sizes = new string[] { "Small" };
string json = JsonConvert.SerializeObject(product);
//{
// "Name": "Apple",
// "Expiry": "2008-12-28T00:00:00",
// "Sizes": [
// "Small"
// ]
//}
string json = #"{
'Name': 'Bad Boys',
'ReleaseDate': '1995-4-7T00:00:00',
'Genres': [
'Action',
'Comedy'
]
}";
Movie m = JsonConvert.DeserializeObject<Movie>(json);
string name = m.Name;
// Bad Boys

Retrieving Number of Objects from JSON String in C#

I have a JSON string below:
{
"data": [
{
//data for first
},
{
//data for second
},
{
//data for third
},
]
}
From this JSON string, I would like to retrieve the number of objects within the "data" element, which in this case, would be 3.
What would be the best approach to accomplish this? I used the .Length property, but that returned a number that I did not expect.
I am using C#.
Since it's a string in C# you need to parse it into something you can use first. Here's a simple way using framework classes.
//obj is your JSON string
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
Dictionary<string,object> csObj =
serializer.Deserialize<Dictionary<string,object>>(obj);
int length = ((ArrayList)csObj["data"]).Count;
When given a generic data structure, JavaScriptSerializer turns arrays into ArrayLists.
Here's an example using Newtonsoft.Json (Json.NET) which is available as a NuGet package.
Usage:
var jsonString = #"{
""data"": [
{
Name: ""Mike"", Age: 30
},
{
Name: ""John"", Age: 42
},
{
Name: ""Tom"", Age: 44
}
]
}";
var example = JsonConvert.DeserializeObject<Example>(jsonString);
// example.Data.Length == 3 at this point
Classes
class Example
{
public Person[] Data { get; set; }
}
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
You need to first deserialize your json string to get objects. The below post has a couple examples. After you deserialize you should have a collection of your data objects in c# (not a string). From there you should be able to call collection.Count or array.Length depending on what collection type you are using.
C# automatic property deserialization of JSON

Categories

Resources