Fetch Unique Column Values from a JArray - c#

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

Related

Add a list in an existing JSON value

So I have below call to a method where my argument is a json string of this type
var jsonWithSearchData = await querySearchData(jsonOut);
jsonOut ->
[
{
"data": {
"_hash": null,
"kind": "ENY",
"id": "t123",
"payload": {
"r:attributes": {
"lok:934": "#0|I"
},
"r:relations": {
"lok:1445": "15318",
"lok:8538": "08562"
},
"r:searchData": "",
"r:type": [
"5085"
]
},
"type": "EQT",
"version": "d06"
}
}
]
The querySearchData() returns me two list something like this :["P123","P124","P987"] and ["Ba123","KO817","Daaa112"]
I want to add this list in my r:searchData key above. The key inside my searchData i.e. r:Porelation and ClassA and ClassB remains static. So I would like my searchData in my input Json to finally become something like this.
"r:searchData": {
"r:Porelation":{
"ClassA": ["P123","P124","P987"],
"ClassB": ["Ba123","KO817","Daaa112"]
}
},
How can I do this? What I tried:
JArray jfinObject = JArray.Parse(jobjects);
jfinObject["r:searchData"]["r:relations"]["ClassA"] = JArray.Parse(ListofCode.ToString());
And I get below error:
System.Private.CoreLib: Exception while executing function: Function1.
Newtonsoft.Json: Accessed JArray values with invalid key value:
"r:searchData". Int32 array index expected.
There are a few ways you can add a node/object/array to existing json.
One option is to use Linq-to-Json to build up the correct model.
Assuming you have the json string described in your question, the below code will add your desired json to the r:searchData node:
var arr = JArray.Parse(json); // the json string
var payloadNode = arr[0]["data"]["payload"];
// use linq-to-json to create the correct object
var objectToAdd = new JObject(
new JProperty("r:Porelation",
new JObject(
new JProperty("r:ClassA", array1),
new JProperty("r:ClassB", array2))));
payloadNode["r:searchData"] = objectToAdd;
where array1 and array2 above could come from a linq query (or just standard arrays).
// Output:
{
"data": {
"_hash": null,
"kind": "ENY",
"id": "t123",
"payload": {
"r:attributes": {
"lok:934": "#0|I"
},
"r:relations": {
"lok:1445": "15318",
"lok:8538": "08562"
},
"r:searchData": {
"r:Porelation": {
"r:ClassA": [
"P123",
"P456"
],
"r:ClassB": [
"Ba123",
"Ba456"
]
}
},
"r:type": [
"5085"
]
},
"type": "EQT",
"version": "d06"
}
}
Online demo
Another option is to create the json from an object, which could be achieved using JToken.FromObject(). However, this will only work if you have property names which are also valid for C# properties. So, this won't work for your desired property names as they contain invalid characters for C# properties, but it might help someone else:
// create JToken with required data using anonymous type
var porelation = JToken.FromObject(new
{
ClassA = new[] { "P123", "P456" }, // replace with your arrays here
ClassB = new[] { "Ba123", "Ba456" } // and here
});
// create JObject and add to original array
var newObjectToAdd = new JObject(new JProperty("r:Porelation", porelation));
payloadNode["r:searchData"] = newObjectToAdd;

Get only one variable from json response

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();

'Accessed JObject values with invalid key value: 1. Object property name expected.'

I am trying to get JSON data from an api.
I have this json with me:
{
"elements": [
{
"id": 1,
"name": "Bob",
"address": "abc street",
"hobbies": {
"indoor": "Games, reading books",
"outdoor": ""
}
},
{
"id": 2,
"name": "Mark",
"address": "def street",
"hobbies": {
"indoor": "Games, reading books",
"outdoor": ""
}
}
]
}
I have this code with me:
using(var httpClient = new HttpClient()) {
HttpResponseMessage response = httpClient.GetAsync("api_url_here").Result;
var studentJsonString = response.Content.ReadAsStringAsync().Result;
var Jsresult = new JavaScriptSerializer().Deserialize<dynamic>(studentJsonString).ToString();
JObject jObject = JObject.Parse(Jsresult);
IEnumerable<dynamic> listDyn = jObject[0].Select(items => new StudentModel// gives error here as whole
{
id = items["id"].ToString(),
name = items["name"].ToString(),
address= items["address"].ToString()
});
}
But when I am calling the above method but it is giving me an error:
'Accessed JObject values with invalid key value: 1. Object property name expected.'
What am I missing?
Why are you deserializing twice? The result of
JavaScriptSerializer().Deserialize(customerJsonString)
is already an object. You don't need to parse it again with JObject.Parse(). You can just do
JObject jObject= JObject.Parse(customerJsonString)
Furthermore the result of JObject.Parse() is a dictionary and not an array. It has properties, which you can access by their names. For instance
jObject["elements"]
But of course, the compiler can't possibly predict, that jObject["elements"] will be an IEnumerable, so you will have to make sure of that.
jObject.Value<JArray>("elements").Select(item => ...)
This reads the property elements, of jObject as a JArray.

Convert a list of JToken to a list of one of the values

I have a list of json JTokens:
List<JToken> subjectresults = jObj[jp]["subjects"].Children().ToList();
Note that my jp is var jp = jObj.Properties().First().Name; because the name is dynamic.
Each of the tokens contains two further items, a url and a name.
I want to get a list of strings that contains just the name value, from this list of jtokens.
So that:
[0]: {{
"url": "https://openlibrary.org/subjects/science",
"name": "Science"
}}
[1]: {{
"url": "https://openlibrary.org/subjects/in_library",
"name": "In library"
}}
Becomes:
{"Science", "In library"}
I can't seem to figure out the syntax.
Or alternatively how do I skip the tokens and go right to my list.
I didn't strongly type this, because the parent property has the dynamic name, and I only needed a couple of the fields.
I suppose that subjects-property is Array:
var jObj = JObject.Parse(json);
var jp = jObj.Properties().First().Name;
var subjectresults = jObj[jp]["subjects"]
.Children()
.Select(v => v["name"].Value<string>())
.ToArray();
/*
subjectresults
{string[2]}
[0] [string]:"Science"
[1] [string]:"In library"
*/
The source json:
var json = #"{
""name"": {
""subjects"": [
{
""url"": ""https://openlibrary.org/subjects/science"",
""name"": ""Science""
},
{
""url"": ""https://openlibrary.org/subjects/in_library"",
""name"": ""In library""
}
]
}
}";

Read all dynamic name and value from JSON string

I need to get all dynamic name and values from JSON string. I am going to create one function with JSON string parameter. that parameter JSON string name and values can change, But I need to print all names and values from that JSON string.
Example code :
json : { "data":
[{
"id": "001",
"Name": "Somu",
"Address": "Erode",
},
{
"id": "002",
"Name": "Ajal",
"Address": "USA",
}]
}
I want to Get all values from this JSON with in loop. Property name may change or increase property count.I need to get all values from passed JSON.
Expected Result : 1 st loop
Id = 001
Name =Somu
Address =Erode
2 nd loop
Id = 002
Name =Ajal
Address =USA
Using Json.Net
string json = #"{ ""data"": [ { ""id"": ""001"", ""Name"": ""Somu"", ""Address"": ""Erode"", }, { ""id"": ""002"", ""Name"": ""Ajal"", ""Address"": ""USA"", }] }";
var result = JObject.Parse(json)
["data"]
.Select(x => new
{
id = (string)x["id"],
Name = (string)x["Name"],
Address = (string)x["Address"],
})
.ToList();
or more dynamic versions
var result = JObject.Parse(json)
["data"]
.Select(x=> x.Children().Cast<JProperty>()
.ToDictionary(p=>p.Name,p=>(string)p.Value))
.ToList();
.
var result = JObject.Parse(json)["data"]
.ToObject<List<Dictionary<string,string>>>();

Categories