JSON SelectTokens expression - c#

I have a JSON file (below). My goal is to, fill a dictionary with unit_ids (f.e. in this JSON unit_ids are: 153470, 153471 and 178903) and corresponding classtype_id (f.e. in this JSON corresponding classtype_id are: CW,CW, null). (unit_ids are uniqe)
So f.e. my dictionary might be: {[153470, CW],[153471, CW],[178903, null]}.
But there is a problem, in my current approach, because of the possibility of: "unit_id":null like f.e. in this file: "178903": null.
Dictionary<string, string> unit_id_translate = new Dictionary<string, string>();
var unitIdsTypes = JObject.Parse(unit_ids_json).SelectTokens("*.['classtype_id']");
var unitIdsNumbers = JObject.Parse(unit_ids_json);
List<String> tempForUID = new List<String>();
List<String> tempForVAL = new List<String>();
foreach (var unitIdType in unitIdsTypes)
{
tempForVAL.Add(unitIdType.ToString());
}
foreach (var unitIdNumber in unitIdsNumbers)
{
foreach (var tmp44 in unitIdNumber)
{
var trimmedNr = unitIdNumber.Cast<JProperty>().Select(o => o.Name);
foreach (var unitIdNr in trimmedNr)
{
tempForUID.Add(unitIdNr);
}
break;
}
}
for (int i = 0; i < tempForUID.Count(); i++)
{
unit_id_translate.Add(tempForUID.ElementAt(i), tempForVAL.ElementAt(i));
}
I need help, because my solution crashes (out of range exception) - there is more unit_ids than classtype_id - because of the null value.
What I can do to fix this ?
{
"153470": {
"topics": {
"en": ""
},
"classtype_id": "CW",
"learning_outcomes": {
"en": ""
},
"course_id": "06-DRSOLI0",
"course_name": {
"en": "Distributed operating systems"
},
"id": 153470,
"teaching_methods": {
"en": ""
}
},
"153471": {
"topics": {
"en": ""
},
"classtype_id": "CW",
"learning_outcomes": {
"en": ""
},
"course_id": "06-DPROLI0",
"course_name": {
"en": "Team project"
},
"id": 153471,
"teaching_methods": {
"en": ""
}
},
"178903": null,
}

You can do this easily with Enumerable.ToDictionary():
var unit_id_translate = JObject.Parse(unit_ids_json)
.Properties()
.ToDictionary(p => p.Name, p => (string)p.Value.SelectToken("classtype_id"));
Then
Console.WriteLine(JsonConvert.SerializeObject(unit_id_translate));
produces {"153470":"CW","153471":"CW","178903":null}.

Related

How to search and get only sub document using C# mongoDB

I have data in provinces collection like this:
{
"_id": {
"$oid": "63dc7ff82e7e5e91c0f1cd87"
},
"province": "province1",
"districts": [
{
"district": "district1",
"sub_districts": [
{
"sub_district": "sub_district1",
"zip_codes": [
"zip_code1"
]
},
{
"sub_district": "sub_district2",
"zip_codes": [
"zip_code2"
]
},
],
},
],
}
This is how I get a list of sub_district for now:
- I search for province using Builders.Filter.
- Use foreach to get districts array (In province collection) and use if-statement to check if district equal searchDistrict.
- Get sub_districts array in that distric.
Source code:
public static List<string> MongoDbSelectSubDistrict(string searchProvince, string searchDistrict)
{
List<string> subDistrictList = new List<string>();
try
{
var provincesCollection = _db.GetCollection<BsonDocument>("provinces");
var builder = Builders<BsonDocument>.Filter;
var filter = builder.Empty;
if (searchProvince != "")
{
var provinceFilter = Builders<BsonDocument>.Filter.Eq("province", searchProvince);
filter &= provinceFilter;
}
/*
//***Need to be revised***
if (searchDistrict != "")
{
var districtFilter = Builders<BsonDocument>.Filter.Eq("provinces.district", searchDistrict);
filter &= districtFilter;
}
*/
var queryProvinces = provincesCollection.Find(filter).ToList();
foreach (BsonDocument queryProvince in queryProvinces)
{
BsonArray districtArray = queryProvince.GetValue("districts").AsBsonArray;
foreach (BsonDocument districtDocument in districtArray)
{
string district = districtDocument.GetValue("district").ToString();
if (district == searchDistrict) //***Need to be revised***
{
BsonArray subDistrictArray = districtDocument.GetValue("sub_districts").AsBsonArray;
foreach (BsonDocument subDistrictDocument in subDistrictArray)
{
string subDistrict = subDistrictDocument.GetValue("sub_district").ToString();
subDistrictList.Add(subDistrict);
}
}
}
}
}
catch (TimeoutException ex)
{
}
return subDistrictList;
}
Is there any efficient way to get this?
This is what I want:
[
{
"sub_district": "sub_district1",
"zip_codes": [
"zip_code1"
]
},
{
"sub_district": "sub_district2",
"zip_codes": [
"zip_code2"
]
},
]
And one more question: if I want to search for sub_district in the collection, how do I get this without looping in sub_districts array?

Update mongoDB document in bulk in C#

I have multiple document like below in mongo collection(giving just one sample).
{
"_id": "5fdb",
"createddate": "2020-12-17",
"orders": [
{
"_id": "4c65",
"sourcesystemrecordid": null,
"accepteddate": "2020-12-19",
"fulfillment": [
{
"_id": "7d3ceb",
"createdby": "Azekry",
"systemid": "123",
"systemrecordname": "source1"
}
]
}
]
}
Under fulfilment, I want to update "systemid" value from "123" to "789" for all the documents where "systemrecordname" = "source1" and for that I have written below piece of code but the data is not updated. Can you help me on this?
foreach (var item in resultFromDatabse)
{
var ordr = item.orders;
foreach (var e in ordr)
{
var actualval = "789";
foreach (var ef in e.fulfillment.Where(x => x.systemrecordname == "source1"))
{
filter = builder.Eq("systemrecordname", ef.systemrecordname);
var update = Builders<EquipmentDemandPlan>.Update.Set("orders.$[e].fulfillment.$[ef].systemid", actualval);
UpdateOneModel<EquipmentDemandPlan> updateOne = new UpdateOneModel<EquipmentDemandPlan>(filter, update)
{
ArrayFilters = new List<ArrayFilterDefinition> {
new BsonDocumentArrayFilterDefinition<BsonDocument>(new BsonDocument("ef.systemrecordname", ef.systemrecordname))
}
};
bulkupdate.Add(updateOne);
}
}
}
collection.BulkWriteAsync(bulkupdate);
you only need arrayFilters in $set
db.collection.update({
"orders.fulfillment.systemrecordname": "source1"
},
{
$set: {
"orders.$[o].fulfillment.$[f].systemid": "789"
}
},
{
arrayFilters: [
{
"o._id": {
$exists: true
}
},
{
"f.systemrecordname": "source1"
}
],
multi: true
})
mongoplayground

Get chrome bookmarks from json

I want to scrape chrome bookmarks using json object. What I want to do is get all bookmarks from 1 folder. That is the structure of the json:
{
"checksum": "d499848083c2c2e3a38f547da4cbad7c",
"roots": {
"bookmark_bar": {
"children": [ {
"children": [ {
"url": "https://www.example.com/"
}, {
"url": "https://www.another-example.com/"
} ],
"name": "foo",
} ],
"name": "Menu bookmarks",
},
"other": {
"name": "Another bookmarks",
},
"synced": {
"name": "Phone bookmarks",
}
},
"version": 1
}
In this case I want to get urls from folder foo. I am using Json.NET to convert string into object. This code:
string input = File.ReadAllText(bookmarksLocation);
using (StringReader reader = new StringReader(input))
using (JsonReader jsonReader = new JsonTextReader(reader)) {
JsonSerializer serializer = new JsonSerializer();
var o = (JToken)serializer.Deserialize(jsonReader);
var allChildrens = o["roots"]["bookmark_bar"]["children"];
var fooFolder = allChildrens.Where(x => x["name"].ToString() == "foo");
foreach (var item in fooFolder["children"]) {
Console.WriteLine(item["url"].ToString());
}
Console.ReadKey();
}
Is giving me an error:
Cannot apply indexing with [] to an expression of type 'IEnumerable<JToken>'
Can you tell me what I did wrong?
there is 1 loop is missing:
var fooFolder = allChildrens.Where(x => x["name"].ToString() == "foo");
foreach (var folder in fooFolder)
{
foreach (var item in folder["children"])
{
Console.WriteLine(item["url"].ToString());
}
}

Linq in JSON.NET

I have a json string as below
{
'Sheet1': [{
'EmployeeNo': '123456',
'EmployeeName': 'Midhun Mathew'
}, {
'EmployeeNo': '123457',
'EmployeeName': 'Bill Gates'
}, {
'EmployeeNo': '123456',
'Address': 'AAAA'
}, {
'EmployeeNo': '123457',
'Address': 'BBBB'
}]
}
JObject parsedJson = JObject.Parse(jsonString);
// Get the EmployeeNo's
List<JToken> tokenList = parsedJson["Sheet1"]
.GroupBy(d => d["EmployeeNo"])
.Select(s => s.Key)
.ToList();
// Get the tokens which have the Same 'EmployeeNo'
foreach (JToken j in tokenList)
{
IEnumerable<JToken> t = parsedJson["Sheet1"].Where(s => s["EmployeeNo"] == j);
}
But in the foreach I am getting only the first one which is
{
"EmployeeNo": "123456",
"EmployeeName": "Midhun Mathew"
}
I am not getting what I am doing wrong here.
My original intent is to group the JTokens having same EmployeeNo into one JObject
So in the above case I will get 2 JObjects since there are 2 different EmployeeNo's
Hope I am clear
It's not entirely clear what you're trying to do here, but you seem to be grouping by EmployeeNo, then throwing away the results to get just the keys, and then trying to do the grouping again in a more manual way.
If you remove the Select(s => s.Key) part, then you could just use the groupings directly:
var tokensByEmployeeNo = parsedJson["Sheet1"].GroupBy(x => x["EmployeeNo"]);
foreach (var grouping in tokensByEmployeeNo)
{
Console.WriteLine($"Key: {grouping.Key}");
foreach (var token in grouping)
{
Console.WriteLine(token);
}
}
If you want to create a 'new' JObject for each of these groupings, then you probably want to create a JArray per group:
var groupedArrays = parsedJson["Sheet1"]
.GroupBy(x => x["EmployeeNo"])
.Select(groupedRecords => new JArray(groupedRecords));
The first of these would look like this, for example:
[
{
"EmployeeNo": "123456",
"EmployeeName": "Midhun Mathew"
},
{
"EmployeeNo": "123456",
"Address": "AAAA"
}
]
If you just wanted to go through the list of Employees, here's how I am used doing:
var json = #"
{
'Sheet1': [{
'EmployeeNo': '123456',
'EmployeeName': 'Midhun Mathew'
}, {
'EmployeeNo': '123457',
'EmployeeName': 'Bill Gates'
}, {
'EmployeeNo': '123456',
'Address': 'AAAA'
}, {
'EmployeeNo': '123457',
'Address': 'BBBB'
}]
}";
var array = JArray.Parse(JObject.Parse(json).SelectToken("Sheet1").ToString());
foreach (var arrayElement in array)
{
var employeeNo = JObject.Parse(arrayElement.ToString()).SelectToken("EmployeeNo");
var employeeName = JObject.Parse(arrayElement.ToString()).SelectToken("EmployeeName");
Console.WriteLine("Number: {0}, Name: {1}", employeeNo, employeeName);
}
Output:

parse specific json string on wp8 app

I'm creating wp8 application and have to parse specific json string:
string jsonStr = {
"ver": "1",
"item1": {
"name": "name1",
"desc": "desc1"
},
"item2": {
"name": "name2",
"desc": "desc2"
},
"item3": {
"name": "name3",
"desc": "desc3"
}
}
I need values of key name to get in list, eg. name1, name2, name3. I was trying to find similar situation but with no success.
This works, but I think there will be more elegant way to solve this problem. However you can use it.
var jsonStr = "{\"ver\":\"1\",\"item1\":{\"name\":\"name1\",\"desc\":\"desc1\"},\"item2\":{\"name\":\"name2\",\"desc\":\"desc2\"},\"item3\":{\"name\":\"name3\",\"desc\":\"desc3\"}}";
List<string> names = new List<string>();
JObject jsonObject = JObject.Parse(jsonStr);
jsonObject.Remove("ver");
foreach (JToken jsonRow in jsonObject.Children())
{
foreach (JToken item in jsonRow)
{
foreach (JToken itemProperty in item)
{
var property = itemProperty as JProperty;
if (property != null && property.Name == "name")
{
if (property.Value != null)
{
names.Add(property.Value.ToString());
}
}
}
}
}

Categories

Resources