Dynamically Adding to JArray generates repeated data - c#

When I write this code:
string[] title= {"title1","title2","title3","title4"};
int[] iid= {124,122,333,234};
dynamic bucket = new JObject();
bucket.bucket = "Parking Lot";
bucket.roadmap = new JArray();
dynamic issue = new JObject();
dynamic json2 = new JArray(bucket);
for(int i=0; i<title.Length; i++) {
issue.title = title[i];
issue.iid = iid[i];
issue.order = i;
bucket.roadmap.Add(issue);
}
Console.WriteLine(json2.ToString());
My result is:
[
{
"bucket": "Parking Lot",
"roadmap": [
{
"title": "title4",
"iid": 234,
"order": 3
},
{
"title": "title2",
"iid": 122,
"order": 1
},
{
"title": "title3",
"iid": 333,
"order": 2
},
{
"title": "title4",
"iid": 234,
"order": 3
}
]
}
]
The first and last "roadmap" JObjects got repeated. There is a way if dynamically generate this JSON with their unique values I want to pass?
I also tried to do it non-dynamically.
JArray bucket = new JObject();
bucket.Add("bucket","Parking Lot");
bucket.Add("order", new JArray());
JObject issue = new JObject();
...
But I could not find a way to select "bucket.order.Add" to add issues to that JArray.
In the end, I am just trying to loop through a JArray with a bunch of data and I want to separate it from their bucket type, extract each issue value and store it in a new JSON, with the structure shown here.
Thanks

Create a new issue object before adding to the array.
for(int i=0; i<5; i++) {
issue = new JObject();
issue.title = "Elbow\"";
issue.iid = 123;
issue.order = i;
bucket.roadmap.Add(issue);
}

Related

How to convert json to Dictionary

I have to convert the JSON string to Dictionary< string, object >. For that, I am following something here https://www.programming-books.io/essential/csharp/collect-all-fields-of-json-object-5293c4c9342c403bb40dd9232692a7bc and doing DotNotation to convert it to Dictionary however, the output is not as expected.
JSON Data I am trying:
{
"name": "Madame Uppercut",
"age": 39,
"secretIdentity": "Jane Wilson",
"powers": [
"Million tonne punch",
"Damage resistance",
"Superhuman reflexes"
],
"accounting": [
{
"firstName": "John",
"lastName": "Doe",
"age": 23
},
{
"firstName": "Mary",
"lastName": "Smith",
"age": 32
}
]
}
Using the code from above link and converting from DotNotation as below
var dictionary = new Dictionary<string, object>();
foreach (var jsonInput in dotNotation)
{
var hierarchy = jsonInput.Key.Split('.');
var bottom = dictionary;
for (int i = 0; i < hierarchy.Length; i++)
{
var key = hierarchy[i];
if (i == hierarchy.Length - 1)
{
bottom.Add(key, jsonInput.Value);
}
else
{
if (!bottom.ContainsKey(key))
bottom.Add(key, new Dictionary<string, object>());
bottom = (Dictionary<string, object>)bottom[key];
}
}
}
finally, the result is like.
Now, what I want is to group the arrays(powers and accounting). I know the JToken path is giving '[]' array path but I want it like below for power and account in the dictionary.
{[power, [{"Million tonne punch" }, {"Damage resistance" }, {"Superhuman reflexes"}]]}
Use Json.NET
var values = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);

Query JSON Nested Object using LINQ

I have the below JSON where I'm trying to query the average confidence value and count of shape objects. I am using Newtonsoft to create the Json Object and to parse the Json Object. I'm gettiing error as "Cannot cast Newtonsoft.Json.Linq.JObject to Newtonsoft.Json.Linq.JToken". I understand I am treating object as array and hence the error, but I don't know how to treat the nested object. Please help.
{
"channel":{
"description": "James Newton-King\"s blog.",
"region":[
{
"title": "Json.NET 1.3 + New license + Now on CodePlex",
"description": "Announcing the release of Json.NET 1.3",
"link": "http://james.newtonking.com/projects/json-net.aspx",
"shape":{
"square":{
"type":"number",
"text":"$81.22",
"confidence":0.983
},
"circle":{
"type":"string",
"valueString":"50741890",
"text":"50741890",
"confidence":1.0
},
"rectangle":{
"type":"date",
"text":"01/01/2020",
"confidence":1.0
}
}
}
],
"errors":[
]
}
}
//My code
public void qryNode()
{
string json = File.ReadAllText(#"C:\Extract.json");
JObject rss = JObject.Parse(json);
var categories =
from c in rss["channel"]["region"].SelectMany(i => i["shape"]).Values<string>()
group c by c
into g
orderby g.Count() descending
select new { Category = g.Key, Count = g.Count() };
foreach (var c in categories)
{
Console.WriteLine(c.Category + " - Count: " + c.Count);
}
}
Once you have JObject parsed, you can get requested result like this:
var jObject = JObject.Parse(json);
var shapes = jObject["channel"]["region"]
.SelectMany(j => j["shape"]);
var confidences = shapes
.SelectMany(s => s.Select(i => i["confidence"]
.Value<float>()))
.ToList();
var result = new
{
ShapesCount = confidences.Count,
AverageConfidence = confidences.Average()
};
You can easily query with direct LINQ keywords like this
considering this JSON
{
"items": [
{
"id": "10",
"name": "one"
},
{
"id": "12",
"name": "two"
}
]
}
let's put it in a variable called json like this,
JObject json = JObject.Parse("{'items':[{'id':'10','name':'one'},{'id':'12','name':'two'}]}");
you can select all ids from the items where name is "one" using the following LINQ query
var Ids =
from item in json["items"]
where (string)item["name"] == "one"
select item["id"];
Then, you will have the result in an IEnumerable list

How to create JSON String with nested array of values using JSON.NET?

Thanks to #don-jayamanne and #dbc for mentioned that my JSON needed to be well-formed
Here is my rephrased question:
Our application at work is using JSON.NET to create JSON Strings.
Here is the JSON string that I'm trying to create:
{
"RouteID": "123321213312",
"DriverName": "JohnDoe",
"Shift": "Night",
"ItineraryCoordinates": [
[
9393,
4443
],
[
8832,
3322
],
[
223,
3432
],
[
223,
3432
]
]
}
Here is the faulty code that I wrote to create the aforementioned JSON String:
writer.WriteStartObject();
writer.WritePropertyName("RouteID");
serializer.Serialize(writer, routeID);
writer.WritePropertyName("DriverName");
serializer.Serialize(writer, driverName);
writer.WritePropertyName("Shift");
serializer.Serialize(writer, shift);
writer.WritePropertyName("ItineraryCoordinates");
ItineraryCoordinatesCollectionFactory tpCollFac = new ItineraryCoordinatesCollectionFactory();
ItineraryCoordinates anItineraryCoordinates;
StringBuilder coordSB = new StringBuilder();
IList<TimePeriod> ItineraryCoordinatesCollection = tpCollFac.createItineraryCoordinatesCollection();
for (int j = 0; j < ItineraryCoordinatesCollection.Count(); j++)
{
anItineraryCoordinates = ItineraryCoordinatesCollection[j];
writer.WriteStartObject();
writer.WritePropertyName("nested");
coordSB.Append(anItineraryCoordinates.StartTimePeriodCoordinate.X.ToString());
coordSB.Append(" , ");
coordSB.Append(anItineraryCoordinates.StartTimePeriodCoordinate.Y.ToString());
serializer.Serialize(writer, coordSB.ToString());
writer.WriteEndObject();
coordSB.Clear();
writer.WriteStartObject();
writer.WritePropertyName("nested");
coordSB.Append(aTimePeriod.EndTimePeriodCoordinate.X.ToString());
coordSB.Append(" , ");
coordSB.Append(aTimePeriod.EndTimePeriodCoordinate.Y.ToString());
serializer.Serialize(writer, coordSB.ToString());
coordSB.Clear();
writer.WriteEndObject();
} // end of for (int j = 0; j < OrderedTimePeriodsCollection.Count(); j++)
writer.WriteEndObject(); // closing off Json Object LogEventsTimePeriods
I keep getting the following error whenever I change the location of writer.WriteStartObject() within the code:
Token StartObject in state Object would result in an invalid JSON object. Path ''.
Could someone please give a rough code draft as to how I can write out the JSON String I want using JSON.NET?
As said on comments your JSON is not valid, It probably should be:
{
"RouteID": "123321213312",
"DriverName": "JohnDoe",
"Shift": "Night",
"ItineraryCoordinates": [
[ 9393, 4443 ],
[ 8832, 3322 ],
[ 223, 3432 ],
[ 223, 3432 ]
]
}
Here you have a sample that shows you two approaches to build the sample JSON:
public class Route
{
public string RouteID { get; set; }
public string DriverName { get; set; }
public string Shift { get; set; }
public int[][] ItineraryCoordinates;
public static string GetSampleJson() {
var sampleRoute = new Route
{
RouteID = "123321213312",
DriverName = "JohnDoe",
Shift = "Night",
ItineraryCoordinates = new int[][] {
new int[] {9393, 4443 },
new int[] { 8832, 3322 },
new int[] { 223, 3432 },
new int[] { 223, 3432 }
}
};
return JsonConvert.SerializeObject(sampleRoute, Formatting.Indented);
}
public static string GetSampleJson2()
{
var route = new JObject(
new JProperty("RouteID", "123321213312"),
new JProperty("DriverName", "JhonDoe"),
new JProperty("Shift", "Night"),
new JProperty("ItineraryCoordinates", new JArray(
new JArray(9393, 4443),
new JArray(8832, 3322 ),
new JArray( 223, 3432 ),
new JArray( 223, 3432)
)
));
return route.ToString();
}
}

Create JSON from 2 strings from Database (Latency and Formatting Issues)

I have created a JSON file from JArray in MVC application from 2 coloumns of my Database. But there are 2 issues:
1. The format of the file. It has extra brackets for each object.
[
[
{
"Code": "1",
"Name": "ASSETS"
}
],
[
{
"Code": "2",
"Name": "LIABILITIES"
}
],
[
{
"Code": "3",
"Name": "CAPITAL"
}
],
[
{
"Code": "4",
"Name": "REVENUE"
}
]
]
I want it as:
[
{
"Code": "1",
"Name": "ASSETS"
},
{
"Code": "2",
"Name": "LIABILITIES"
},
{
"Code": "3",
"Name": "CAPITAL"
},
{
"Code": "4",
"Name": "REVENUE"
}
]
I have loaded the values in JArray from Database and then add it in another JArray. I am using 2 for loops. 1 for making JArray for 5000 entries. And the second for returning the next valid primary key from Database. But the problem is that, it takes more than 15 minutes to process the loops and return the JSON file. Why is there so much latency? And how can I make it fast. Here is the code.
int idd =0;
JArray Array = new JArray();
for (int b = 0; b<5000; b++)
{
idd = dbid(idd);
IEnumerable<MST> accList = new List<MST>
{
new MST
{
S1 = db.MSTs.Find(idd).S1,
S2 = db.MSTs.Find(idd).S2
}
};
JArray Arrayone = new JArray(
accList.Select(p => new JObject
{
{ "Code", p.S1 },
{ "Name", p.S2 },
})
);
Array.Add(Arrayone);
}
string jsonfile = JsonConvert.SerializeObject(Array,Formatting.Indented);
string path = #"C:\Users\Awais\Desktop\accounts.json";
System.IO.File.WriteAllText(path, jsonfile);
return View(v);
}
public int dbid(int id)
{
decimal i = db.MSTs.Max(a => a.N100);
MST m = new MST();
for (; id <= i; id++)
{
m = db.MSTs.Find(++id);
if (m == null)
continue;
else
{
break;
}
}
return id;
}
When I tried the first loop for 100 entries, it took about 60 seconds to return the file.
By modeling your JSON with anonymous type, you could've done it like this:
var array = (from coa in db.MSTs
select new { Code = coa.S2, Name = coa.S1 }).ToArray();
string jsonfile = JsonConvert.SerializeObject(array, Formatting.Indented);
string path = #"C:\Users\Awais\Desktop\accounts.json";
System.IO.File.WriteAllText(path, jsonfile);
It took me 319 ms for 100 000 objects.
Try:
public class RootObject
{
public string Code { get; set; }
public string Name { get; set; }
}
var o = new List<RootObject>();
for (var i = 0; i < 100; ++i)
{
o.Add(new RootObject
{
Code = "foo",
Name = "bar"
});
}
var v = JsonConvert.SerializeObject(o);
Took around 274 milliseconds for my list to Serialize.
I have removed all loops and instead try to solve it in query and making a single array.
var k = (from coa in db.MSTs
select new { S2 = coa.S2, S1 = coa.S1 }).ToList().
Select(x => new MST { S2 = x.S2, S1 = x.S1 }).ToList();
JArray Arrayone = new JArray(
k.Select(p => new JObject
{
{ "Code", p.S1 },
{ "Name", p.S2 },
})
);
string jsonfile = JsonConvert.SerializeObject(Arrayone,Formatting.Indented);
string path = #"C:\Users\Awais\Desktop\accounts.json";
System.IO.File.WriteAllText(path, jsonfile);
It solves both problems. i.e. Brackets formatting issue and latency. Now with this code it works in less than 5 seconds

what is the c# object to save the data in this formate

I have this string
string[] xInBGraph = { "IVR", "Agents", "Abandoned", "Cancelled" };
and I have these values:
int ivr = 1;
int agents = 2;
int abandoned = 3;
int cancelled = 4;
What I need
To make an array for each element in the array xInBGraph in which the new array should contain one value and the other values are zero. For example This is how the final result will be
IVR = [ivr =1, 0 , 0 ,0, 0]
Agents = [0, agents=2, 0,0]
Abandoned = [0, 0, abandoned = 3, 0]
Cancelled = [0, 0, 0, cancelled = 0]
what I have tried
making 4 arrays and fill them in the correct data. It works good. However, my altimate goal is to transfer that final result to a json object. I need to return just on json object. but in my case, which is 4 arrays, I must return 4 json objects which is not good for my situation. I need to return just on json object. So, what is the object in c# that can have the mentioned data and can be transfer to one json object?
I am using json.net library so I can easily change any c# object to json object
Edit
I made these four arrays:
int[] ivrArray = { Tivr, 0, 0, 0};
int[] agentsArray = { 0, tTotalCallsByAgent, 0, 0 };
int[] abandonedArray = { 0, 0, tTotalAbandoned, 0};
int[] canceledArray = { 0, 0, 0, Tcancel};
Now all I need is something to save the label of each array and the array in one row.
I would suggest you use a Dictionary. Specifically,
Dictionary<string,int[]> dictionary = new Dictionary<string,int[]>()
{
{ "IVR", new int[] {1,0,0,0} },
{ "Agents", new int[] {0,2,0,0} },
{ "Abandoned", new int[] {0,0,3,0} },
{ "Cancelled", new int[] {0,0,0,0} },
}
Hope this is what you are expecting
string[] xInBGraph = { "IVR", "Agents", "Abandoned", "Cancelled" };
List<string[]> final = new List<string[]>();
for (int i = 0; i < xInBGraph.Count(); i++)
{
List<string> array = new List<string>();
for (int x = 0; x < xInBGraph.Count(); x++)
{
if (x == i)
{
array.Add(xInBGraph[i].ToString() + "=" + x);
}
else
{
array.Add("0");
}
}
final.Add(array.ToArray());
}
string json = JsonConvert.SerializeObject(final, Formatting.Indented);
Output
[ [ "IVR=0", "0", "0", "0" ], [ "0", "Agents=1", "0", "0" ], [ "0", "0", "Abandoned=2", "0" ], [ "0", "0", "0", "Cancelled=3" ] ]

Categories