c# to query a json file - c#

I have a json file as such:
{
"rowId": "39",
"refNumber": "19",
"title": "Mobile",
"date": "10/29/2015",
"status": "saved"
}{
"rowId": "10",
"refNumber": "478",
"title": "Completion",
"date": "10/30/2015",
"status": "saved"
}{
"rowId": "11",
"refNumber": "604",
"title": "Online Order",
"date": "10/30/2015",
"status": "failed"
}
What I'd like to do is query the json file in c# like as such with a winforms app:
string qrySaved = "select count(*) as total from file where status = 'saved'";
string qryFailed = "select count(*) as total from file where status = 'failed'";
Then place the results in two variables.
I did the following:
logFolder = Directory.GetCurrentDirectory();
logFolder = logFolder.Replace("\\bin\\Debug", "\\metrics");
logFile = logFolder + #"\log.json";
I'm using the Newtonsoft.Json nuget resource and know how to read the first object but can't figure out how to query the file to return total counts based on a given element.

You can try something like this:
static void Main(string[] args)
{
string json = File.ReadAllText("sample1.json");
var array = JArray.Parse(json);
int savedcount = array.Count(i => i["status"].Value<string>() == "saved");
int failedcount = array.Count(i => i["status"].Value<string>() == "failed");
}
Might a typo but the JSON posted was invalid so I changed it as below to make it work:
[
{
"rowId": "39",
"refNumber": "19",
"title": "Mobile",
"date": "10/29/2015",
"status": "saved"
},
{
"rowId": "10",
"refNumber": "478",
"title": "Completion",
"date": "10/30/2015",
"status": "saved"
},
{
"rowId": "11",
"refNumber": "604",
"title": "Online Order",
"date": "10/30/2015",
"status": "failed"
}
]

Related

Find all Id's in json object

I have a long tree json document, here is the part of it
"childs": [
{
"id": "id1",
"name": "name1",
"childs": []
},
{
"id": "id2",
"name": "name21",
"childs": [
{
"id": "id3",
"name": "name123124",
"childs": [
{
"id": "id4",
"name": "namewe1231",
"childs": [
{
"id": "id5",
"name": "name123123",
"childs": [
{
"id": "id5",
`
i need to save all id from this document for local storage like:
id1
id2
id3
id4 etc...
is it even possible? JObject and dynamic variable didnt help me.
heres code i've been trying to compile but it returned me just first id from tree
`
string source = File.ReadAllText(jsonModelPath);
dynamic data = JObject.Parse(source);
File.WriteAllText(path, data.id);
`
you can try something like this
string[] ids = JObject.Parse(json)
.Descendants()
.OfType<JProperty>()
.Where(a => a.Name == "id")
.Select(a => a.Value.ToString())
.ToArray();
or you can put all ids in one line
string strIds = string.Join(" ",ids);
or each id in the new line
string strIds = string.Join("\n",ids);
and save
File.WriteAllText(path, strIds);

C# base16 encoded SHA256 string function not returning expected result

I have a function that is attempting to return a lower case base 16 encoded hash of a request body for signing the AWS API, as detailed in the hashed payload section here.
Given the following JSON string -
{
"shipTo": {
"name": "A3",
"addressLine1": "SWA Test Account",
"addressLine2": "SWA Test Account",
"addressLine3": "SWA Test Account",
"stateOrRegion": "",
"postalCode": "DN1 1QZ",
"city": "Doncaster",
"countryCode": "GB",
"email": "test+test#amazon.com",
"phoneNumber": "444-444-4444"
},
"shipFrom": {
"name": "A1",
"addressLine1": "4 Neal Street",
"stateOrRegion": "",
"postalCode": "WC2H 9QL",
"city": "London",
"countryCode": "GB",
"email": "test+test#amazon.com",
"phoneNumber": "444-444-4444"
},
"packages": [
{
"dimensions": {
"length": 3.14,
"width": 3.14,
"height": 3.14,
"unit": "INCH"
},
"weight": {
"unit": "KILOGRAM",
"value": 3.14159
},
"items": [
{
"quantity": 1,
"itemIdentifier": "V-02",
"description": "Sundries",
"isHazmat": false,
"weight": {
"unit": "KILOGRAM",
"value": 1.14159
}
},
{
"quantity": 1,
"itemIdentifier": "V-01",
"description": "Sundries",
"isHazmat": false,
"weight": {
"unit": "KILOGRAM",
"value": 1.14159
}
}
],
"insuredValue": {
"unit": "GBP",
"value": 29.98
},
"packageClientReferenceId": "abcd"
}
],
"channelDetails": {
"channelType": "EXTERNAL"
}
}
I am expecting a return value of 71d826b7bab4af808f73033e81154bce32fed66f1270393d8b0fa05839a6fb29 as displayed in successful postman calls for the same JSON value.
However, I am getting a value of 16f1382cc1db6988693b66e49597811e46f4210c284c82cbc37b6a9f58c61bf5, which throws off subsequent signing values, and causes the call to fail.
Here is the function that takes the JSON string and returns the hash -
public static string HashRequestBody(string stringToHash)
{
byte[] hashedBytes = new SHA256Managed().ComputeHash(Encoding.UTF8.GetBytes(stringToHash));
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hashedBytes.Length; i++)
{
sb.Append(hashedBytes[i].ToString("x2", CultureInfo.InvariantCulture));
}
return sb.ToString();
}
What would be causing the differences in hashed payload values in my code as opposed to the Postman call for the same request body?
It turns out that the hash was different due to the line breaks included in my JSON object.
You can read more here, but the short of it is Microsoft uses \r\n for line breaks by default, and the hash Amazon is calculating is using only \n as a line break.
I resolved this by serializing the object to a string and replacing \r\n with the expected \n values, like so:
body = Regex.Replace(body, #"\r\n?|\n", "\n");

Filter data from deep json child

the JSON below is taken from other post. My issue is I know the id and I want to find out where is it located. Eg, I got ID 19006 and I want to get Folder2. How am I going to do this.
{
"data": {
"id": 0,
"name": "",
"childFolders": [{
"id": 19002,
"name": "Locker",
"childFolders": [{
"id": 19003,
"name": "Folder1",
"childFolders": [],
"childComponents": [{
"id": 19005,
"name": "route1",
"state": "STOPPED",
"type": "ROUTE"
}]
}, {
"id": 19004,
"name": "Folder2",
"childFolders": [],
"childComponents": [{
"id": 19008,
"name": "comm1",
"state": "STOPPED",
"type": "COMMUNICATION_POINT"
}, {
"id": 19006,
"name": "route2",
"state": "STOPPED",
"type": "ROUTE"
}, {
"id": 19007,
"name": "route3",
"state": "STOPPED",
"type": "ROUTE"
}]
}],
"childComponents": []
}],
"childComponents": []
},
"error": null
}
I write code now it is like this:
var json = GetJsonString();
var model = GetJsonModel(json);
var folderName = GetName(model.data, 19006);
I chekced and code is correct. folderName is Folder2
And the recursive code:
private string GetName(Data data, int searchValue)
{
var folderName = data.name;
foreach (var item in data.childComponents)
{
if (item.id == searchValue)
{
return folderName;
}
}
if (data.childFolders.Length > 0)
{
foreach (var item in data.childFolders)
{
var folderName1 = GetName(item, searchValue);
if (folderName1 != null)
{
return folderName1;
}
}
}
return null;
}
Your model is like this:
EDIT:
I parse Json like this.
return JsonSerializer.Deserialize<YourJson>(test);

How to get all value of particular key in JSON?

I have a JSON structure that contains different levels. How to iterate the JSON and get all values of a particular key in JSON in C#
Below is my JSON file
{
"name": "EPM Company",
"id": "kpfwzgmhpm",
"type": "root",
"childern": [
{
"cid": "67",
"cname": "cname1",
"childern": [
{
"reading": [
{
"id": 121,
"name": "test1"
},
{
"id": 1121,
"name": "test11"
}
]
}
]
},
{
"cid": "454",
"cname": "cname14",
"childern": [
{
"reading": [
{
"id": 454,
"name": "test14"
},
{
"id": 21,
"name": "test141"
}
]
}
]
}
]
}
This is the JSON format. I am trying to get the value in the below format.
{
"name": "EPM Company",
"id": "kpfwzgmhpm",
"value": [
{
"id": 121,
"name": "test1",
"cid": "67",
"cname": "cname1"
},
{
"id": 1121,
"name": "test11",
"cid": "67",
"cname": "cname1"
},
{
"id": 124234,
"cname": "test12342",
"cid": "67",
"name": "cname1"
},
{
"id": 454,
"name": "test14",
"cid": "454",
"cname": "cname14"
},
{
"id": 21,
"name": "test141",
"cid": "454",
"cname": "cname14"
},
{
"id": 121,
"name": "test123122",
"cid": "454",
"cname": "cname14"
}
]
}
fetching all the reading key and its value-added to array with its cid and came. is it possible?
advanced thanks for the help
my code in c# is
public string SensorList(string entireData)
{
if (string.IsNullOrEmpty(entireData))
{
return string.Empty;
}
var returnObj = new Jobject ();
JObject o = JObject.Parse(entireData);
var childern = o["children"];
returnObj.Add("name" = o ["name"];
returnObj.Add("id" = o ["id"];
returnObj.Add("value" = o ["value"];
var valuearry = new JArray();
foreach(var data in childern)
{
foreach(var reading in data["reading"])
{
var valobj = new Jobject ();
valobj.Add( "cid",data["id"])
valobj.Add( "cname",data["name"])
valobj.Add( "name",reading["id"])
valobj.Add( "id",reading["name"])
valuearry.add()
if(data.containsKey("children"))
{
var sensorInfo = SensorList(data["children"]);
}
}
returnObj.Add("value",valuearry);
// var output = sensorInfo.SelectMany(x => ((JObject)x).Properties().Select(y => new JObject {
// new JProperty("id",y.Name),
// new JProperty("name",y.Value["name"])
// })).ToList();
// var returnArray = new JArray(output);
return returnObj.ToString();
}
}
recurring part is not working and take too much time for other long JSON file

Is there a way to sum the values directly in C# without hitting cosmosDB and run a query?

I am trying to find a way to sum the prices held in an array, the way I am doing it now is to save the document to CosmosDB then run an additional sum(foo) query on it but I am thinking there must be a way so simply do that directly before I save the document to CosmosDB to save the extra round trip to the DocumentDB.
Example Document below.
The values I want to summarise are under:
ApiInputObject.TransactionDetails.Items.Price and there can of course be many items in the array.
I can only figure out how to get a single value out but that seems very inefficient.
{
"InternalTransactionlId": "XXX",
"DocumentType": "order",
"ExternalTransactionId": "externalIdTest2",
"OrderBotResponse": {
"id": "XXX",
"status": "pending",
"checkoutUrl": "https://www.example.com",
"items": [
{
"attributes": {
"color": "Midnight blue",
"size": "L"
},
"price": "500",
"quantity": "1",
"shipping": "0.0",
"title": "ACME Title",
"url": "https://example.com",
"product_id": "XXX",
"imageUrl": "https://example.com/image.jpg",
"status": "pending",
"shippingMethod": "default",
"totalPrice": 500
}
],
"reference": "XXX",
"currency": "SEK",
"country": "SE",
"language": "sv-se",
"provider": "acme",
"callback": {
"refund": "http://example.com",
"success": "http://example.com"
},
"shippingAddress": {},
"logs": [
{
"t": "2019-08-24T20:58:04.844+08:00",
"m": "Created"
}
],
"meta": {
"error": 0
}
},
"ApiInputObject": {
"ApiKey": "XXX",
"OrderType": "directTransaction",
"SourceSystem": {
"SourceSystemName": "ACME"
},
"SourceSystemCountry": "SE",
"DestinationSystem": {
"DestinationSystemName": "acme.com"
},
"DestinationSystemCountry": {
"DestinationSystemCountryName": "SE"
},
"Brand": {
"BrandName": "ACME"
},
"RequestedFeatures": [
"NONE"
],
"ExternalTransactionId": "externalIdTest2",
"TransactionDetails": {
"callback": {
"refund": "http://example.com",
"success": "http://example.com"
},
"items": [
{
"attributes": {
"color": "Midnight blue",
"size": "L"
},
"price": "500",
"quantity": "1",
"shipping": "0.0",
"title": "ACME",
"url": "https://example.com"
}
],
"test": "true",
"reference": "XXX"
}
},
"id": "XXX",
"_rid": "XXX",
"_self": "XXX",
"_etag": "XXX",
"_attachments": "attachments/",
"_ts": 111
}
You can try to use SelectToken to get your JSON data value. then use linq SUM
JObject obj = JObject.Parse(data);
var value = obj.SelectToken("ApiInputObject.TransactionDetails.items").Sum(x=>((int)x["price"]));
c# online

Categories