Convert json data to DataTable or DataRow without loop - c#

Hi every one it is possible to convert json to debatable without doing loop
{
"ipAddress": "10.203.10.162",
"portNo": 45462,
"protocol": "HTTP",
"macAddress": "98:df:82:86:a4:27",
"channelID": 1,
"dateTime": "2023-01-11T14:57:24+04:00",
"activePostCount": 1,
"eventType": "AccessControllerEvent",
"eventState": "active",
"eventDescription": "Access Controller Event",
"AccessControllerEvent": {
"deviceName": "Access Controller",
"majorEventType": 5,
"subEventType": 75,
"name": "ahmad",
"cardReaderKind": 1,
"cardReaderNo": 1,
"verifyNo": 159,
"employeeNoString": "1",
"serialNo": 868,
"userType": "normal",
"currentVerifyMode": "cardOrFaceOrFp",
"currentEvent": false,
"frontSerialNo": 867,
"attendanceStatus": "breakOut",
"label": "Break Out",
"statusValue": 0,
"mask": "unknown",
"helmet": "unknown",
"picturesNumber": 1,
"purePwdVerifyEnable": true
}
}
I tried the following code and it return error.
DataTable dt = JsonConvert.DeserializeObject(json);

You have to flatten your JObject and only after this you can deserialize it to DataTable
var jo=JObject.Parse(json);
jo.Merge(jo["AccessControllerEvent"]);
jo.Remove("AccessControllerEvent");
DataTable dt = new JArray(jo).ToObject<DataTable>();

I suggest looking at uses of map: map documentation.
Under the hood, this of course is doing a for loop of a kind.
Perhaps you are trying to avoid the 'traditional' for loop, for this i use :
Object.Keys(yourJsonObect).foreach((key) => {
const someDataFromkey = yourJsonObect[key];
});
I hope that helps.

Related

Count the total sub nodes in a JSON using Newtonsoft.Json

I am trying to find the count of the total nodes inside a file which is in JSON format. I tried the below code and it is not working. Googled few but couldn't find what I am looking for. I am new to JSON file handling, please guide me.
Json Input 1:
{
"CandidateId": "E3",
"Ngocentre": "Chennai",
"FirstName": "XXX",
"LastName": "YYY",
"PhoneNumber": 22221,
"EmailId": "E3#gmail.com",
"EducationalQualification": "Graduate",
"SkillSet": "ASP.NET",
"CreatedByNgo": "Gurukul",
"UpdatedByNgo": "Gurukul",
"CreatedDate": "0001-01-01T00:00:00",
"ModifiedDate": "0001-01-01T00:00:00",
"NgoemailId": "gurukul#gmail.com"
}
** Json Input 2:**
[
{
"CandidateId": "E3",
"Ngocentre": "Chennai",
"FirstName": "XXX",
"LastName": "YYY",
"PhoneNumber": 22221,
"EmailId": "E3#gmail.com",
"EducationalQualification": "Graduate",
"SkillSet": "ASP.NET",
"CreatedByNgo": "Gurukul",
"UpdatedByNgo": "Gurukul",
"CreatedDate": "0001-01-01T00:00:00",
"ModifiedDate": "0001-01-01T00:00:00",
"NgoemailId": "gurukul#gmail.com"
},
{
"CandidateId": "E3",
"Ngocentre": "Chennai",
"FirstName": "XXX",
"LastName": "YYY",
"PhoneNumber": 22221,
"EmailId": "E3#gmail.com",
"EducationalQualification": "Graduate",
"SkillSet": "ASP.NET",
"CreatedByNgo": "Gurukul",
"UpdatedByNgo": "Gurukul",
"CreatedDate": "0001-01-01T00:00:00",
"ModifiedDate": "0001-01-01T00:00:00",
"NgoemailId": "gurukul#gmail.com"
}
]
My ideal output should be "1" for the 1st input and "2" for the 2nd input. I tried the below code.
using (StreamReader r = new StreamReader(#"C:\Users\xxx\Desktop\Read.txt"))
{
string json = r.ReadToEnd();
dynamic source = JsonConvert.DeserializeObject(json);
int count = ((Newtonsoft.Json.Linq.JContainer)((Newtonsoft.Json.Linq.JToken)source).Root).Count;
}
But when pass only the 1st input, I am getting count as 13 which is the total properties inside a Json.
Above code piece returns 2 for the 2nd input which is the ideal output, but it fails when I pass 1st input alone.
you can just count the tokens :
if (json.StartsWith("["))
{
// If the json is an array
var array = JArray.Parse(json);
Console.WriteLine(array.Count);
}
else
{
// If the json is only one object, the result is 1.
// I added a way to retieve the object as token array :
var jobject = JObject.Parse(json);
var tokens = jobject.SelectTokens("$"); // You can go through you object : jobject.SelectTokens("$.CandidateId") => "E3"
Console.WriteLine(tokens.Count());
}
An other solution would be the Regex with atomic group.
Parsing the array manually is overkill, you just need to parse a JArray out of it.
using (StreamReader r = new StreamReader(#"C:\Users\xxx\Desktop\Read.txt"))
{
var array = JsonSerializer.CreateDefault().Deserialize<JArray>(r);
Console.WriteLine(array.Count);
}

How do I take a JSON string and select a random entry and get the variables from that entry

I have the following json..
{
"Followers": [{
"ID": 0,
"Username": "nutty",
"Game": "Just Chatting",
"Viewers": 200,
"Image": "https://static-cdn.jtvnw.net/previews-ttv/live_user_nutty-1920x1080.jpg"
}, {
"ID": 1,
"Username": "CloneKorp",
"Game": "Software and Game Development",
"Viewers": 31,
"Image": "https://static-cdn.jtvnw.net/previews-ttv/live_user_clonekorp-1920x1080.jpg"
}, {
"ID": 2,
"Username": "kingswarrior9953",
"Game": "Art",
"Viewers": 1,
"Image": "https://static-cdn.jtvnw.net/previews-ttv/live_user_kingswarrior9953-1920x1080.jpg"
}]
}
I'd like to do something like..
JObject data = JObject.Parse(json);
int SelectedViewers = data["Followers"][1]["Viewers"];
Where it would grab the second entry (the ID of 1 entry) and set the variable of "Viewers" to 31. The number would be a random number based on the count of all the entries, but I'm not to that point yet.
However, this doesn't seem to work. Any ideas on what is broken here?
You are missing casting here:
int SelectedViewers = Int32.Parse((string)data["Followers"][1]["Viewers"]);
The above should work.
try this
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
var followers = (JArray)JObject.Parse(json)["Followers"];
var id=1;
int selectedViewers = followers.Where(f=> (int)f["ID"]==id)
.Select(f => (int) f["Viewers"])
.FirstOrDefault(); //31

Need to convert JSON to datatable

I have incoming JSON formatted like this:
{
"users": [
{
"radio_id": "123582",
"callsign": "ABCD",
"name": "First Last",
"city": "Dortmund",
"state": "Nordrhein-Westfalen",
"country": "Germany",
"home_rptr": "W2VL",
"remarks": "None"
},
{
"radio_id": "789456",
"callsign": "EFG",
"name": "Name Here",
"city": "Dortmund",
"state": "Nordrhein-Westfalen",
"country": "Germany",
"home_rptr": "W2VL",
"remarks": "None"
}
]
}
It is coming from a web request that I catch into a string called dataReceived. I then use this line of code to convert to a datatable.
DataTable dtData = (DataTable)JsonConvert.DeserializeObject(dataReceived, (typeof(DataTable)));
I'm getting an error of:
Unexpected JSON token when reading DataTable. Expected StartArray, got StartObject. Path '', line 1, position 1.
I suspect my problem is the data is in an array, but I'm not sure how to solve this. My objective is to have a table with each row one of the "users" objects in the json.
Can anyone push me in the right direction?
var dt = JObject.Parse(json)["users"].ToObject<DataTable>();
That is all.

Printing out the first index of an array in JSON format

What I am trying to do is print out the first index of an array in JSON format.
With the code:
storeInformation = myStoreInfoTable;
strResponseOutput = JsonConvert.SerializeObject(storeInformation);
These are the results:
[
{
"distance": 0,
"descr": "Toronto",
"address": "1300 Castlefield Avenue",
"city": "Toronto"
},
{
"distance": 7.1121883392,
"descr": "Etobicoke - North",
"address": "Resources Road",
"city": "Etobicoke"
}
]
What I tried to do to get the first index is:
storeInformationRow = dtbStoreInformation.Rows[0];
strResponseOutput = JsonConvert.SerializeObject(storeInformationRow);
What I get is:
{
"RowError": "",
"RowState": 2,
"Table": [
{
"distance": 0.0000000000,
"descr": "Toronto",
"address": "1300 Castlefield Avenue",
"city": "Toronto"
},
{
"distance": 7.1121883392,
"descr": "Etobicoke - North",
"address": "Resources Road",
"city": "Etobicoke"
}
]
}
The result I want is just
{
"distance": 0.0000000000,
"descr": "Toronto",
"address": "1300 Castlefield Avenue",
"city": "Toronto"
}
Help anybody?
I seems to me that the JSON serializer is goofing up because it doesn't know how to correctly serialize a DataRow. That's the only difference between the first and second snippet of code.
If you look at the MSDN documentation for the DataRow class you can see that the DataRow has the attributes displayed (RowError, RowState and Table) among many others.
To fix your problem I would suggest one of 2 options:
Create a new DataTable and add the DataRow you want to serialize to it, and call JsonConvert.SerializeObject() on that.
Map the columns (distance, descr, address & city) to another class (Store or something) and try to serialize that object. From what I read in the JsonConvert documentation it's possible (the class attributes are mapped correctly onto the JSON object).
Let me know how it goes!
you can just use :
var row = dtbStoreInformation.Rows[0];
string strResponseOutput = new {
distance = row[0].ToString(),
descr= row[1].ToString(),
address = row[2].ToString(),
city = row[2].ToString()}.ToJson();
don't forget the include of the namespace ServiceStack.Text
You can also create an anonym object
var obj = jsonString = new {
distance = row[0].ToString(),
descr= row[1].ToString(),
address = row[2].ToString(),
city = row[2].ToString()}
strResponseOutput = JsonConvert.SerializeObject(obj);

JSON C# Parsing Error

This is my JSON
{
"3659639": {
"EventID": 3659639,
"RaceNum": 2,
"Meeting": "Newton Abbot",
"RaceType": "T",
"Description": "Attheraces.Com Handicap Chase",
"Distance": "5300m",
"TrackCondition": "Good",
"Weather": "Overcast",
"Abandoned": 0,
"SuspendDateTime": "2014-06-17 00:00:42.0000000",
"OutcomeDateTime": "2014-06-17 00:00:00.0000000",
"EffectiveRaceDate": "2014-06-16",
"Status": "Paying",
"Results": [
{
"event_id": 3659639,
"saddle_number": 11,
"position": 1,
"status": "Final"
},
{
"event_id": 3659639,
"saddle_number": 16,
"position": 2,
"status": "Final"
},
{
"event_id": 3659639,
"saddle_number": 17,
"position": 3,
"status": "Final"
}
],
"Dividends": {
"0": {
"event_id": 3659639,
"source": "NSW",
"pool_type": "Duet",
"outcome": "11\/16",
"pool_value": 79.5,
"interim_dividend": 11.2,
"final_dividend": 11.2
},
"36": {
"event_id": 3659639,
"source": "VIC",
"pool_type": "Trifecta",
"outcome": "11\/16\/17",
"pool_value": 1733,
"interim_dividend": 2746.2,
"final_dividend": 2746.2
},
"37": {
"event_id": 3659639,
"source": "VIC",
"pool_type": "Win",
"outcome": "11",
"pool_value": 2541.06,
"interim_dividend": 25.5,
"final_dividend": 25.5
},
"RunnerProducts": {
"11": {
"TopeTotePlace": 12,
"MidTotePlace": 7.3,
"TopeToteWin": 29.8,
"MidToteWin": 28,
"BestOrSP": 29.8
},
"16": {
"TopeTotePlace": 2.3,
"MidTotePlace": 2
},
"17": {
"TopeTotePlace": 26.4,
"MidTotePlace": 24.2
}
}
}
},
"3622800": {
"EventID": 3622800,
"RaceNum": 2,
"Meeting": "Albion Park",
"RaceType": "H",
"Description": "Seymour Rising Stars Championship C0 Heat One",
"Distance": "1660m",
"TrackCondition": "Good",
"Weather": "Fine",
"Abandoned": 0,
"SuspendDateTime": "2014-06-17 15:09:10.0000000",
"OutcomeDateTime": "2014-06-17 15:08:00.0000000",
"EffectiveRaceDate": "2014-06-17",
"Status": "Closed",
"Results": [
],
"Dividends": {
"RunnerProducts": [
]
}
},
"3679673": {
"EventID": 3679673,
"RaceNum": 6,
"Meeting": "Thirsk",
"RaceType": "T",
"Description": "Market Cross Jewellers Handicap",
"Distance": "1200m",
"TrackCondition": null,
"Weather": null,
"Abandoned": 0,
"SuspendDateTime": "2014-06-18 02:20:00.0000000",
"OutcomeDateTime": "2014-06-18 02:20:00.0000000",
"EffectiveRaceDate": "2014-06-17",
"Status": "Open",
"Results": [
],
"Dividends": {
"RunnerProducts": [
]
}
}
}
I am trying to parse this using JSON.Net and i have tried this code.
var obj = JObject.Parse(json);
var query =
from JProperty ev in obj.AsJEnumerable()
from JProperty evid in ev.Value.AsJEnumerable()
let value = (JObject)evid.Value
select new
{
Description = (string)value["Description"]
};
I am getting this error "Unable to cast object of type 'Newtonsoft.Json.Linq.JValue' to type 'Newtonsoft.Json.Linq.JObject'."
i also want to read event_id which is inside results and dividents. Can anyone tell me what i am doing wrong here
Currently, you're getting the properties of the properties - and then trying to cast each of the values to JObject, and then taking the Description of that. That's one level too deep, as you have:
The root object
Each property of the root object, which genuinely has an object as its value
Each property of each of those values... most of which are just string properties, so the value can't be cast to JObject
It's not clear why you're using AsJEnumerable() at all, but all you need is the properties of the root object, which is easily obtained with the Properties() method. Likewise it's not clear why you're using an anonymous type, rather than just getting a sequence of strings. This works fine:
var query =
from ev in obj.Properties()
select (string) ev.Value["Description"];
Or without the query syntax:
var query = obj.Properties.Select(ev => (string) ev.Value["Description"]);
Next:
i also want to read event_id which is inside results and dividents
In the data you've given, that's always the same as the value of the EventID property in the top-level type. So you'd be better off with:
var query =
from ev in obj.Properties()
select new { Description = (string) ev.Value["Description"],
Id = (string) ev.Value["EventID"] };
If you really want to get at the values in the dividends and results, you'll need to work out how you'll handle the multiple entries in those properties.

Categories