Get only one variable from json response - c#

I make a POST request and I get back json response with a lot of transactions in it like:
"Transactions": [
{
"ID": "1",
"Name" : "name",
"Code": "123aaa"
},
{
"ID": "2",
"Name" : "name1",
"Code": "12345bbb"
}
]
Is there any simple way to get one variable (for example first "Code" value)? Without entity classes etc?
I've tried this
var content = new StringContent(request, Encoding.UTF8, "application/json");
var response = await HttpClient.PostAsync(postURL, content);
var text = await response.Content.ReadAsStringAsync();
var code = JObject.Parse(text).Children().First().Values<string>("Code").First();
But it didn't work:
System.InvalidOperationException : Cannot access child value on Newtonsoft.Json.Linq.JValue.

Assuming that provided json is actually an object (i.e. string in question is wrapped in curly brackets) - you can use json path:
var code = JObject.Parse(text).SelectToken("$.Transactions[0].Code").ToString(); // results in "123aaa"
If you are keen on using LINQ to JSON you can do something like this:
var code = JObject.Parse(text)
.Descendants()
.OfType<JProperty>()
.Where(p => p.Name == "Code")
.Select(p => p.Value.ToString())
.FirstOrDefault();
But the easiest I think would be to use indexers:
var code = JObject.Parse(text)["Transactions"][0]["Code"].ToString();

Related

How to extract a field from JSON

Using NewtonSoft, I am able to parse JSON into this:
var jtoken = JObject.Parse(stringStuff);
Console.WriteLine(jtoken.ToString());
gives this:
{
"data": {
"user": {
"email": "john#doe.com",
"external-id": "af36-e9fddecdb755"
},
"session-token": "G_uJNNxmLNtxcmM2ilB6P_dN67p9XXk3-yn8peUBi7k3xH50Ch7MUQ+C"
},
"context": "/sessions"
}
However, if I try to get the field "session-token" like this,
var token = jtoken.Value<string>("session-token");
token is null. Not sure what I am doing wrong?
a "session-token" property is nested inside of a "data" property
string token = (string) jtoken["data"]["session-token"]; // G_uJNNxmLNtxcmM2ilB6P_dN67p9XXk3-yn8peUBi7k3xH50Ch7MUQ+C
You need to run through the descendants of your root object, and find the JProperty with the name you want -
var token = root.Descendants()
.OfType<JProperty>()
.Where(x => x.Name == "session-token")
.FirstOrDefault()
?.Value
?.Value<string>();
if(token != null)
{
//token is "G_uJNNxmLNtxcmM2ilB6P_dN67p9XXk3-yn8peUBi7k3xH50Ch7MUQ+C"
}
It's a little awkward, the first .Value returns the JProperty's JToken, then the second .Value gets the string value.

Fetch Unique Column Values from a JArray

I am trying to get only Unique IDs from a JSON response. I tried to parse and select only token Ids but it is failing. What is the best and fastest way to get only the Ids?
Code:
JArray jArray = new JArray();
var response = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
response.Content = new StringContent(jArray.ToString(Formatting.Indented));
var resp = await response.Content.ReadAsStringAsync();
Here is my sample JSON Array:
[
{
"Timestamp": "2020-11-24T08:25:46.6531855Z",
"ID": "8c316aca-b930-421f-851c-17d618b61fa1",
"Message": "New User Registered"
},
{
"Timestamp": "2020-11-24T08:25:46.6531855Z",
"ID": "8c316aca-b930-421f-851c-17d618b61fa1",
"Message": "User details updated"
},
{
"Timestamp": "2020-11-24T08:25:46.6531855Z",
"ID": "a23shaga-2wd3-fky6-851c-43524fbfgsa",
"Message": "New User Registered"
}
]
Desired Output:
8c316aca-b930-421f-851c-17d618b61fa1
a23shaga-2wd3-fky6-851c-43524fbfgsa
This will give you the distinct ID values from your JArray, filtering out possible nulls:
jArray = JArray.Parse(resp);
var ids = jArray.Children<JObject>()
.Select(jo => (string)jo["ID"]) // NOTE: this is case sensitive
.Where(s => s != null)
.Distinct()
.ToList();
Demo here: https://dotnetfiddle.net/gaQ1n0
Best way is to create the object with the properties timestamp, id and message- then deserialize the json to this object.
But for now you can try below and should work out well for you.
JArray jArray = new JArray();
jArray = JArray.Parse(#"[
{
""Timestamp"": ""2020-11-24T08:25:46.6531855Z"",
""ID"": ""8c316aca-b930-421f-851c-17d618b61fa1"",
""Message"": ""New User Registered""
},
{
""Timestamp"": ""2020-11-24T08:25:46.6531855Z"",
""ID"": ""8c316aca-b930-421f-851c-17d618b61fa1"",
""Message"": ""User details updated""
},
{
""Timestamp"": ""2020-11-24T08:25:46.6531855Z"",
""ID"":""a23shaga-2wd3-fky6-851c-43524fbfgsa"",
""Message"": ""New User Registered""
}]");
var newList = jArray.Where(y=> !string.IsNullOrEmpty(y["ID"].ToString()))
.GroupBy(x => x["ID"])
.Select(x => x.First()).ToList();
foreach (var item in newList)
{
Console.WriteLine(item["ID"]);
}
Here newList contains only unique data w.r.t 'ID'
Just replace the entire string in my example with the async resp you are getting.
NOTE : You should either make the source return unique or create a new object and deserialize it instead of using JObject, this will help you when you have bigger lists
So below is the outcome i think you are looking for

How take this json path in newtonsoft.json C#

I have been building an application where JSON will be provided from a user API. It should read the data from the JSON using JSONPath and persist the selected portions. I am trying to do this using Json.Net (Newtonsoft). The following JSON is a sample:
{
// other properties here and different structure here
"Data": [
{
"Code": "625087",
"Name": "Customer Name",
"Email": "test#hfgidfgd.com"
},
{
"Code": "625087",
"Name": "Customer Name",
"Email": "test#hfgidfgd.com"
},
{
"Code": "625087",
"Name": "Customer Name",
"Email": "test#hfgidfgd.com"
}
],
// other properties here and different structure here
}
I would like to extract the array presented by the Data property content using JSONPath and convert it to List<Dictionary<string, object>> to manipulate in my application.
In tools like jsonpath.com the following JSONPath query works fine but with Newtonsoft it does not:
// get that json
string content = GetJson();
var jo = JObject.Parse(content);
var jsonPath = "$..Data.*";
var jsonPathResult = jo.SelectTokens(jsonPath, true /* to get error when it is not found */ );
Instead I got the exception:
Property '*' not valid on JArray.
If I do the JSONPath like this:
var jsonPath = "$..Data"; // same for just: "Data"
var jsonPathResult = jo.SelectTokens(jsonPath);
I have to loop on the result with two nested foreach, what I think it is not an elegant solution:
var result = new List<Dictionary<string, object>>();
foreach (var jsonResult in jsonPathResult)
{
foreach (var item in jsonResult)
{
var fields = JsonConvert.DeserializeObject<Dictionary<string, object>>(item.ToString());
// some adjusts on the fields dictionary will be applied here...
result.Add(fields);
}
}
Is there any way to get the result to take a single loop the only the content of Data property?
As shown in JSONPath - XPath for JSON, the syntax for an array element wildcard is [*]. Thus your code should look like:
var jsonPath = "$..Data[*]";
var result = jo.SelectTokens(jsonPath, true /* to get error when it is not found */ )
.Select(o => o.ToObject<Dictionary<string, object>>())
.ToList();
Here I am using JToken.ToObject<T>() to deserialize each array element directly to a Dictionary<string, object>> without re-serializing to a string.
Sample working .Net fiddle.

How to get root value of Json get from dialogflow?

I got the json response from dialogflow. Now I want to get the "q1" value. So I've tried this:
var stringjson = ApiAiJson<QueryResponse>.Serialize(queryResponse);
var deserializejson =ApiAiJson<QueryResponse>.Deserialize(stringjson);
if (deserializejson.Result.Action == "web.search")
{
JObject jsonob = JObject.Parse(stringjson);
string q = jsonob["parameters"]["q1"].ToString();
System.Console.WriteLine(q);
}
But string q returns "null".
Maybe the deserialisation is wrong. The value is embedded in parameters and not the root value. But I don't know how to get the root value of json.
Plus,here's the json response:
"result": {
"source": "agent",
"resolvedQuery": "search for apple",
"action": "web.search",
"actionIncomplete": false,
"parameters": {
"q1": "apple",
"q2": ""
},
Help!
Use below code:
q = jsonob["result"]["parameters"]["q1"].ToString();

Find and retrieve keyed value from anywhere in JSON string

I'm retrieving JSON which may vary in content items and want to find values associated with particular keys, e.g. in this case "geo_latitude" and "geo_longitude". For clarity, I'm only including those two items in this JSON sample. (It's typically much longer and in no particular order).
[
{
"id": 524616,
"key": "geo_latitude",
"value": "36.1069652"
},
{
"id": 524617,
"key": "geo_longitude",
"value": "-112.1129972"
}
]
This was the best I was able to come up with to parse the JSON. Is there a better way?
var metadataObj = JArray.Parse(postMetadataJsonStr);
var latContainer = metadataObj.Descendants()
.OfType<JObject>()
.Where(x => x["key"] != null &&
x["key"].Value<string>() == "geo_latitude").Select(y => y["value"]);
var latTokenJValue = latContainer.FirstOrDefault();
if (latTokenJValue == null) return;
var latitude = latTokenJValue.ToString();
I would convert your json to a dictionary
var metadataObj = JArray.Parse(postMetadataJsonStr);
var dict = metadataObj.ToDictionary(x => (string)x["key"], x => (double)x["value"]);
Console.WriteLine(dict["geo_latitude"]);

Categories