C# JToken.SelectTokens Method - what JPath expression? - c#

I have json text like this:
{
"course_editions": {
"2014/SL": [
{
"grades": {
"course_units_grades": {
"159715": {
"1": {
"value_symbol": "4",
"exam_session_number": 1,
"exam_id": 198172,
"value_description": {
"en": "good",
}
}
}
},
"course_grades": {}
}
},
{
"grades": {
"course_units_grades": {
"159796": {
"1": {
"value_symbol": "5",
"exam_session_number": 1,
"exam_id": 198259,
"value_description": {
"en": "very good",
}
}
}
},
"course_grades": {}
}
},
I would like to use JToken.SelectTokens Method from Namespace: Newtonsoft.Json.Linq
I've tried like this:
string json_response = GetResponse(sign(url_courses));
var courses_tokens = JObject.Parse(json_response).SelectTokens("['course_editions'].['2014/SL'].[*].['grades'].*")
It doesn't work. I would like to get only these numbers after course_unit_grades and before "1". So in this example only: "159715" and "159796" to be able to use all of them, one by one in
foreach(var lp in courses_tokens) {
}

This is one possible way :
var jobj = JObject.Parse(json);
var coursesTokens = jobj.SelectTokens("course_editions.2014/SL[*].grades.course_units_grades")
.Select(o => o.First) //get the first child of `course_units_grades`
.Cast<JProperty>() //cast to JProperty
.Select(o => o.Name); //get the name of the property
foreach (string coursesToken in coursesTokens)
{
Console.WriteLine(coursesToken);
}
Dotnetfiddle Demo
given json sample at the bottom, the output is as follow :
159715
159796
json sample :
var json = #"{
'course_editions': {
'2014/SL': [
{
'grades': {
'course_units_grades': {
'159715': {
'1': {
'value_symbol': '4',
'exam_session_number': 1,
'exam_id': 198172,
'value_description': {
'en': 'good'
}
}
}
},
'course_grades': {}
}
},
{
'grades': {
'course_units_grades': {
'159796': {
'1': {
'value_symbol': '5',
'exam_session_number': 1,
'exam_id': 198259,
'value_description': {
'en': 'very good'
}
}
}
},
'course_grades': {}
}
}
]
}
}";

Related

C# - Finding a nested object value by dot separated key [duplicate]

I have json text like this:
{
"course_editions": {
"2014/SL": [
{
"grades": {
"course_units_grades": {
"159715": {
"1": {
"value_symbol": "4",
"exam_session_number": 1,
"exam_id": 198172,
"value_description": {
"en": "good",
}
}
}
},
"course_grades": {}
}
},
{
"grades": {
"course_units_grades": {
"159796": {
"1": {
"value_symbol": "5",
"exam_session_number": 1,
"exam_id": 198259,
"value_description": {
"en": "very good",
}
}
}
},
"course_grades": {}
}
},
I would like to use JToken.SelectTokens Method from Namespace: Newtonsoft.Json.Linq
I've tried like this:
string json_response = GetResponse(sign(url_courses));
var courses_tokens = JObject.Parse(json_response).SelectTokens("['course_editions'].['2014/SL'].[*].['grades'].*")
It doesn't work. I would like to get only these numbers after course_unit_grades and before "1". So in this example only: "159715" and "159796" to be able to use all of them, one by one in
foreach(var lp in courses_tokens) {
}
This is one possible way :
var jobj = JObject.Parse(json);
var coursesTokens = jobj.SelectTokens("course_editions.2014/SL[*].grades.course_units_grades")
.Select(o => o.First) //get the first child of `course_units_grades`
.Cast<JProperty>() //cast to JProperty
.Select(o => o.Name); //get the name of the property
foreach (string coursesToken in coursesTokens)
{
Console.WriteLine(coursesToken);
}
Dotnetfiddle Demo
given json sample at the bottom, the output is as follow :
159715
159796
json sample :
var json = #"{
'course_editions': {
'2014/SL': [
{
'grades': {
'course_units_grades': {
'159715': {
'1': {
'value_symbol': '4',
'exam_session_number': 1,
'exam_id': 198172,
'value_description': {
'en': 'good'
}
}
}
},
'course_grades': {}
}
},
{
'grades': {
'course_units_grades': {
'159796': {
'1': {
'value_symbol': '5',
'exam_session_number': 1,
'exam_id': 198259,
'value_description': {
'en': 'very good'
}
}
}
},
'course_grades': {}
}
}
]
}
}";

Aggregating By match date $or with other field in Mongodb in C#

I am using mongo aggregation with match/group. Below is my mongo query & similar i am trying to convert to c#. Able to get date part but struggling for $or part for "ev" field. Need to apply below match/or/group/sort on one collection & lookup on other collection.
db.getCollection("customer").aggregate(
[
{
"$match" : {
"eventTs" : {
"$gte" : ISODate("2020-02-27T00:00:00.000-0500"),
"$lte" : ISODate("2020-02-28T00:00:00.000-0500")
},
$or: [
{ "ev": "JournalAdded" },
{ "ev": "JournalProcessed" },
{ "ev": "JournalModified" },
{ "ev": "JournalVoided" },
{ "ev": "JournalApproved" },
{ "ev": "JournalCancelled" }
]
}
},
{
"$sort" : {
"eid" : 1.0,
"eseq" : 1.0
}
},
{
"$group" : {
"_id" : "$eid",
lastSeq: {$last: "$eseq"},
eventNames:{$push: "$ev"}
}
},
{
"$lookup":
{
from: "xyz",
localField: "_id",
foreignField: "_eid",
as: "Replicated"
}
}
]
);
working c# code:
var match = new BsonDocument
{
{
"$match",
new BsonDocument
{
{ "eventTs", new BsonDocument
{
{ "$gte", startTs },
{ "$lte", endTs }
}
},
{ "ev", "JournalAdded" },
//{ "ev", "JournalProcessed" },
//{ "ev", "JournalModified" },
//{ "ev", "JournalVoided" },
//{ "ev", "JournalApproved" },
//{ "ev", "JournalCancelled" }
}
}
};
var pipeline = new[] { match };
var result = instructionEventsDocs.Aggregate<BsonDocument>(pipeline);
List<BsonDocument> list = result.ToList();
Need c# equivalent of above mongo query. Can anyone help me with this ?
You can also add the BsonArray after the BsonDocument for $or part for "ev" field,look into the answers in this link Adding BSON array to BsonDocument in MongoDB
var match = new BsonDocument
{
{
"$match",
new BsonDocument
{
{ "eventTs", new BsonDocument
{
{ "$gte", startTs },
{ "$lte", endTs }
}
},
{
"$or", new BsonArray {
new BsonDocument
{
{ "ev", "JournalAdded" }
},
new BsonDocument
{
{ "ev", "JournalProcessed" }
}
}
},
}
}
};
Equivalent mongo query
{{ "$match" : { "eventTs" : { "$gte" : ISODate("2020-02-27T05:00:00Z"), "$lte" : ISODate("2020-02-28T05:00:00Z") }, "$or" : [{ "ev" : "JournalAdded" }, { "ev" : "JournalProcessed" }] } }}

Deserialize JSON returned from JsonDiffPatch.Diff() in c#

I am comparing two json objects using JsonDiffPatch.Diff() method and I get the below JSON Structure:
{
"complexity": {
"_t": "a",
"0": {
"phases": {
"_t": "a",
"0": {
"activities": {
"_t": "a",
"_0": [
{
"name": "NAME",
"sortId": 15,
"isCritical": true,
"url": "https://google.com",
"processGroupName": "pgm",
"isDeliverable": "no"
},
0,
0
]
}
}
}
},
"3": {
"phases": {
"_t": "a",
"0": {
"sortId": [
55,
0,
0
]
},
"1": {
"activities": {
"_t": "a",
"_0": [
{
"name": "SName",
"sortId": 12,
"isCritical": false,
"url": "https://google.com",
"processGroupName": "pgm",
"isDeliverable": "Yes"
},
0,
0
]
}
}
}
}
}
}
The result that I want is an object containing List of Phases which contains List of Activities. As per the above JSON I want:
0[Phases and Related Activities]
3[Phases and Related Activities]
I have written the below code:
List<JToken> tokens = diffJson.Children().Children().ToList();
foreach (var token in tokens)
{
//Console.WriteLine(token.ToJson());
var phases = token["0"].Children().Children();
Console.WriteLine(phases.Count());
var activities = phases["0"].Children().Children();
Console.WriteLine();
}
But this will only be for the first set which is for "complexity"["0"]. But how to get the data into an object which contains List.
I have tried the below code also:
JavaScriptSerializer serializer = new JavaScriptSerializer();
dynamic item = serializer.Deserialize<object>(output);
Could anybody help me out in understanding how to Deserialize this complex JSON into simple objects?
I am thinking I will ignore "_t":"a" object under phases and start reading activities(again ignoring "_t": "a" object). Let me see how successful I will be.
Expected Output will be creating objects of below classes:
using System;
using System.Generic;
public class Difference {
public List<Phase> Phases { get; set; }
}
public class Phase {
//For other properties like sortID
public List<Dictionary<string, string>> Properties { get; set; }
public List<Activity> Activites { get; set; }
}
public class Activity {
public string name { get; set; }
public int sortId { get; set; }
public bool isCritical { get; set; }
public string url { get; set; }
public string processGroupName { get; set; }
public string isDeliverable { get; set; }
}
Below is the code which partially works:
JavaScriptSerializer serializer = new JavaScriptSerializer();
dynamic item = serializer.Deserialize<object>(output);
foreach (KeyValuePair<string, dynamic> complexity in item["complexity"])
{
if (complexity.Key != "_t")
{
foreach (KeyValuePair<string, dynamic> phases in complexity.Value["phases"])
{
if (phases.Key != "_t")
foreach (KeyValuePair<string, dynamic> activities in phases.Value["activities"])
{
Console.WriteLine(activities.Value);
}
}
}
}
But this loop breaks when simple key value like sortId comes into picture.
Thanks in Advance.
As per what you have mentioned in the comment on #MarcoSalemo's answer i have modified the Sample Json to suit your requirement the Json now consists of 3 sub documents and 2 with 1 activity each sub-document except for the last one which has 2 activities and a properties object as sortId :
Sample JSON:
var jsonString = #"{
'complexity': {
'_t': 'a',
'0': {
'phases': {
'_t': 'a',
'0': {
'activities': {
'_t': 'a',
'_0': [
{
'name': 'NAME',
'sortId': 15,
'isCritical': true,
'url': 'https://google.com',
'processGroupName': 'pgm',
'isDeliverable': 'no'
},
0,
0
]
}
}
}
},
'1': {
'phases': {
'_t': 'a',
'0': {
'activities': {
'_t': 'a',
'_0': [
{
'name': 'NAME1',
'sortId': 155,
'isCritical': true,
'url': 'https://google.com',
'processGroupName': 'pgm',
'isDeliverable': 'no'
},
0,
0
]
}
}
}
},
'3': {
'phases': {
'_t': 'a',
'0': {
'sortId': [
55,
0,
0
]
},
'1': {
'activities': {
'_t': 'a',
'_0': [
{
'name': 'SName',
'sortId': 12,
'isCritical': false,
'url': 'https://google.com',
'processGroupName': 'pgm',
'isDeliverable': 'Yes'
},
0,
0
],
'_1': [
{
'name': 'SName1',
'sortId': 123,
'isCritical': false,
'url': 'https://google.com',
'processGroupName': 'pgm',
'isDeliverable': 'Yes'
},
0,
0
]
}
}
}
}
}
}";
And the deserialization is achieved as:
var jobj = JObject.Parse(jsonString);
List<Phase> Phases = new List<Phase>();
var complexity = jobj.SelectToken("complexity");
var childrens = complexity.Children().ToList();
for (int i = 1; i < childrens.Count; i++)
{
var activities = new List<Activity>();
var _properties = new List<Dictionary<string, string>>();
var child = childrens[i].Children();//getting all the sub-documets in the json
foreach (var subChild in child)
{
var phases = subChild.SelectToken("phases").Children().ToList();//getting JTokens having key "phases"
for (int j = 1; j < phases.Count; j++)
{
var phaseResult = phases[j].Children().ToList(); //getting all the children of the //phases JToken and itterating over them
foreach (var item in phaseResult)
{
if (item["activities"] != null) //producing the "Activity(s)" object
{
var acts = item.SelectToken("activities").Children().ToList();
for (int k = 1; k < acts.Count; k++)
{
var act = acts[k].Children().ToList();
foreach (var entity in act)
{
var jarvalue = JArray.Parse(entity.ToString()).Children().ToArray()[0].ToString();
var objAct = JsonConvert.DeserializeObject<Activity>(jarvalue);
activities.Add(objAct);
}
}
}
else
{
//if not Activity object than producing Properties object
var _props = item.Children<JToken>().ToList();
var nProeprties = new Dictionary<string, string>();
foreach (var content in _props)
{
var _contentProp = ((Newtonsoft.Json.Linq.JProperty)content); //converting the property object of JtokenType to JProperty to get the Name and JValue
nProeprties.Add(_contentProp.Name, _contentProp.Value.ToString());
}
_properties.Add(nProeprties);
}
}
}
}
Phases.Add(new Phase { Activites = activities, Properties = _properties });//appending the extracted output to the mail object "Phases"
}
As per the above sample json, the serialized output would be something like this:
JsonConvert.SerializeObject(Phases);
[
{
"Properties":[
],
"Activites":[
{
"name":"NAME",
"sortId":15,
"isCritical":true,
"url":"https://google.com",
"processGroupName":"pgm",
"isDeliverable":"no"
}
]
},
{
"Properties":[
],
"Activites":[
{
"name":"NAME1",
"sortId":155,
"isCritical":true,
"url":"https://google.com",
"processGroupName":"pgm",
"isDeliverable":"no"
}
]
},
{
"Properties":[
{
"sortId":"[\r\n 55,\r\n 0,\r\n 0\r\n]"
}
],
"Activites":[
{
"name":"SName",
"sortId":12,
"isCritical":false,
"url":"https://google.com",
"processGroupName":"pgm",
"isDeliverable":"Yes"
},
{
"name":"SName1",
"sortId":123,
"isCritical":false,
"url":"https://google.com",
"processGroupName":"pgm",
"isDeliverable":"Yes"
}
]
}
]
Note:
I am using Newtonsoft.Json to serialize/deserialize the json.
This is just a simple approach there can be many(Even better) to achieve what you want. So, please test it out with your data and let me know if it needs a modification.
Use dynamic and deserialize the json with JSON.NET

how to update key name of JSON in c#?

Is there a way to update JSON key name or Change the existing Keyname of a json?
class NewBands
{
private List<NSongs> _NBandName;
public string NewBandName { get; set; }
public List<NSongs> NBandName
{
get { return _NBandName; }
set { _NBandName = value; }
}
}
class NSongs
{
public string NSongTitle { get; set; }
}
[HttpPost]
public JsonResult Bands()
{
dbBandsEntities dbband = new dbBandsEntities();
var returnjson = dbband.Bands.AsEnumerable().Select(x => new NewBands()
{
NewBandName = x.BandName.ToString(),
NBandName = dbband.BandSongs.AsEnumerable().Where(y => y.BandId == x.Id).Select(z => new NSongs() {
NSongTitle = z.SongTitle
}).ToList()
});
return Json(returnjson, JsonRequestBehavior.AllowGet);
}
Output:
[ {
"NewBandName": "Amber Pacific",
"NBandName": [
{ "NSongTitle": "Fall Back Into My Arms" },
{ "NSongTitle": "If I Fall" },
{ "NSongTitle": "When I Found You" }
] }, {
"NewBandName": "Mayday Parade",
"NBandName": [
{ "NSongTitle": "Misserable at Beast" },
{ "NSongTitle": "The Problem with Big Picture is I can't see" }
] }, {
"NewBandName": "Fm Static",
"NBandName": [
{ "NSongTitle": "Dear God" },
{ "NSongTitle": "Her Father Songs" },
{ "NSongTitle": "Last Train Home" },
{ "NSongTitle": "Tonight" },
{ "NSongTitle": "Black Tattoo" }
] }
I Want to update NBandName to BandName Itself.
Output should be:
{
"NewBandName": "Amber Pacific",
"Amber Pacific": [
{ "NSongTitle": "Fall Back Into My Arms" },
{ "NSongTitle": "If I Fall" },
{ "NSongTitle": "When I Found You" }
]
}......
Instead of creating a list of NewBands objects you may create a list of dictionaries of string keys and object values. This allows to set arbitrary key names on the fly:
var returnjson = dbband.Bands.AsEnumerable().Select(x => new Dictionary<string, object>
{
{ "NewBandName", x.BandName.ToString() },
{
x.BandName.ToString(),
dbband.BandSongs
.AsEnumerable()
.Where(y => y.BandId == x.Id)
.Select(z => new NSongs() {
NSongTitle = z.SongTitle
})
.ToList()
}
});

c# json count node's children

clarifying my question, I would like to use JToken.SelectTokens Method (String) from Namespace: Newtonsoft.Json.Linq. How can I use method SelectTokens("") to get number of children for every node "174637"(unit_id) and "174638"(unit_id) ?. For first node I'm supposed to get 1 and for second 2.
I've tried like this:
foreach (var test in unit_ids) { //takes every unit_id, one by one
var children_of_unit_id = test.SelectTokens("*.[*]").count();
}
But It gives me nothing.
"174637": {
"1": {
"value_symbol": "3",
"exam_session_number": 1,
"exam_id": 207983,
"value_description": {
"en": "satisfactory",
}
}
}
"174638": {
"1": {
"value_symbol": "3",
"exam_session_number": 1,
"exam_id": 207984,
"value_description": {
"en": "satisfactory",
}
}
"2": {
"value_symbol": "3",
"exam_session_number": 2,
"exam_id": 207985,
"value_description": {
"en": "satisfactory",
}
}
}
EDITED
This is original Json:
{
"grades": {
"course_units_grades": {
"173565": {
"1": {
"value_symbol": "3,5",
"exam_session_number": 1,
"exam_id": 208798,
"value_description": {
"en": "satisfactory plus",
"pl": "dst+"
}
}
},
"173566": {
"1": {
"value_symbol": "2",
"exam_session_number": 1,
"exam_id": 208797,
"value_description": {
"en": "unsatisfactory",
}
},
"2": {
"value_symbol": "3",
"exam_session_number": 2,
"exam_id": 208797,
"value_description": {
"en": "satisfactory",
}
}
}
},
"course_grades": {}
}
}
So It looks like this:
foreach (var t in json_grade)//take every "grades" element, one by one
{
var test = t.SelectTokens("['grades'].['course_units_grades']");
foreach (var unit_ids in test)
{
foreach (var test in unit_ids) { //takes every unit_id, one by one
var children_of_unit_id = test.SelectTokens("*.[*]").count();
}
}
}
You can try one of these 2 ways :
foreach (var test in unit_ids)
{
var approach1 = test.Children().Children().Count();
var approach2 = test.First.SelectTokens("*").Count();
}
Dotnetfiddle Demo
Try this:
var token = JToken.Parse(j)["unit_id"][0].ToList().Count;
Sample JSON:
{
"174637": [
{
"1": {
"value_symbol": "3",
"exam_session_number": "1",
"exam_id": "207983",
"value_description": {
"en": "value_description"
}
}
}
],
"174638": [
{
"1": {
"value_symbol": "3",
"exam_session_number": "1",
"exam_id": "207983",
"value_description": {
"en": "value_description"
}
},
"2": {
"value_symbol": "3",
"exam_session_number": "1",
"exam_id": "207983",
"value_description": {
"en": "value_description"
}
}
}
]
}

Categories

Resources