Add a field into JSON array C# - c#

Here is my json Array, i want to add a new field in array but i dont know how to loop it
{
"data": {
"pasca": [
{
"code": "PDI1231",
"name": "Water Bottle",
"status": 1,
"price": 2500,
"type": "plastic"
},
{
"code": "PDI9999",
"name": "Soccel Ball",
"status": 1,
"price": 99123,
"type": "plastic"
}
]
}
}
i want to add a new field in pasca array like this
"pasca": [
{
"code": "PDI1231",
"name": "Water Bottle",
"status": 1,
"price": 2500,
"type": "plastic",
"new_field_1": "new value_1",
"new_field_2": "new value_2"
}
]

If you are using Newtosoft's Json.NET it can be done as simple as that:
var jObj = JsonConvert.DeserializeObject<JObject>(json);
foreach(var el in jObj["data"]["pasca"])
{
el["new_field_1"] = "new value_1";
}

Related

How to retrieve a specific property from a nested JSON object

I have a nested json object which looks like this
{{
"id": "99ed8a1a-68fa-4464-b5cb-f116ede0a520",
"title": "NUnitTestDemo",
"has_children": true,
"level": 0,
"children": [
{
"id": "c41764b1-a59a-420b-b06e-9f97f3876e9b",
"title": "TestScripts",
"has_children": true,
"level": 1,
"children": [
{
"id": "cfba3d9e-d305-464d-9154-cdd2efcb5436",
"title": "SmokeTest",
"has_children": true,
"level": 2,
"children": [
{
"id": "b58596fc-aeab-4f20-8a91-85599c08c0fc",
"title": "TestAdd",
"has_children": false,
"level": 3,
"tag": "mytag,add",
"property": "Testing Addition of Two numbers",
"children": []
},
{
"id": "c819746e-25b9-4c84-8fb4-28794c3b2fe4",
"title": "TestSubtract",
"has_children": false,
"level": 3,
"tag": "mytag,subtract",
"property": "Testing Subtraction of Two numbers",
"children": []
}
]
},
{
"id": "7dce76a3-f318-4d49-920c-1d94b3ec9519",
"title": "SmokeTest1",
"has_children": true,
"level": 2,
"children": [
{
"id": "64bf771d-313b-44ce-b910-27945505dada",
"title": "TestMultiply",
"has_children": false,
"level": 3,
"tag": "mytag,add",
"property": "Testing Addition of Two numbers",
"children": []
},
{
"id": "5d810bc0-a9af-4838-b8eb-5fc7c47e910a",
"title": "TestDivide",
"has_children": false,
"level": 3,
"tag": "mytag,subtract",
"property": "Testing Subtraction of Two numbers",
"children": []
}
]
},
{
"id": "8af09935-93fa-4379-9aa4-9f809055d1ea",
"title": "Sample",
"has_children": true,
"level": 2,
"children": [
{
"id": "407944bd-437e-48cd-8af0-bbd2eb376e72",
"title": "Tests",
"has_children": true,
"level": 3,
"children": [
{
"id": "01223a10-2dda-4e3c-9287-d49b0c08870d",
"title": "SmokeTest2",
"has_children": true,
"level": 4,
"children": [
{
"id": "6e3df5f1-bcca-40a8-9ed5-3eaa74558488",
"title": "TestA",
"has_children": false,
"level": 5,
"tag": "mytag,add",
"property": "Testing Addition of Two numbers",
"children": []
},
{
"id": "0414d2c3-e4c8-4e52-9584-6a9e8516a3e2",
"title": "TestB",
"has_children": false,
"level": 5,
"tag": "mytag,subtract",
"property": "Testing Subtraction of Two numbers",
"children": []
}
]
}
]
}
]
},
{
"id": "7dbfcdfe-f6cb-4942-bcc6-3ec899aec674",
"title": "MyTestFolder",
"has_children": true,
"level": 2,
"children": [
{
"id": "16c3a197-824a-4309-bb97-24d454d448f5",
"title": "MyTestClass",
"has_children": true,
"level": 3,
"children": [
{
"id": "c37f2d67-0db0-49bf-80e0-9e99d7e9d767",
"title": "TestC",
"has_children": false,
"level": 4,
"tag": "mytag,add",
"property": "Testing Addition of Two numbers",
"children": []
},
{
"id": "a91c8c04-8a60-4872-b990-db9f993ddbe5",
"title": "TestD",
"has_children": false,
"level": 4,
"tag": "mytag,subtract",
"property": "Testing Subtraction of Two numbers",
"children": []
}
]
}
]
}
]
}
]
}}
If you notice at every level there is a "children" array. Now, when I am searching for "MyTestFolder" inside the above mentioned json, it is returning me "null".
My function looks like this. It is written in C# and I am using Newtonsoft.json library.
I am using .NET Core 3.1
public JObject RetrieveSpecifiedJsonObject(string propertyName, JObject jsonObject)
{
//propertyName is the property to be retrieved
string title = jsonObject.SelectToken("title").ToString();
if(title != propertyName)
{
JArray childArray = jsonObject.SelectToken("children") as JArray;
for(int i=0; i<childArray.Count; i++)
{
JObject childArrElem = childArray[i] as JObject;
string arrElemTitle = childArrElem.SelectToken("title").ToString();
if(arrElemTitle != propertyName)
{
RetrieveSpecifiedJsonObject(propertyName, childArrElem);
}
else
{
return childArrElem;
}
}//FOR ENDS
return null;
}//IF title != propertyName ENDS
else
{
return jsonObject;
}
}
I guess it has to be a recursive function. But, not getting what to do. When I am searching.
FYI, I can't search like jsonobject["children"][0]["MyTestFolder"]. I may have to search for any node at any point of time. For that, I need to write a generic function.
it returns null because this block doesn't do any action with the result from RetrieveSpecifiedJsonObject
if(arrElemTitle != propertyName)
{
RetrieveSpecifiedJsonObject(propertyName, childArrElem);
}
maybe you should do that:
if(arrElemTitle != propertyName)
{
var result = RetrieveSpecifiedJsonObject(propertyName, childArrElem);
if (result != null)
return result;
}
In addition to what JimmyN wrote in his answer, I'd say that you could simplify your recursive function as such (you already check the title property at the top of the function, so you don't need to check it again inside the for loop):
public JObject RetrieveSpecifiedJsonObject(string propertyName, JObject jsonObject)
{
//propertyName is the property to be retrieved
string title = jsonObject.SelectToken("title").ToString();
if(title != propertyName)
{
JArray childArray = jsonObject.SelectToken("children") as JArray;
for(int i=0; i<childArray.Count; i++)
{
JObject childArrElem = childArray[i] as JObject;
// the following will already check childArray and all of its children
JObject result = RetrieveSpecifiedJsonObject(propertyName, childArrElem);
if(result != null)
return result;
}//FOR ENDS
return null;
}//IF title != propertyName ENDS
else
{
return jsonObject;
}
}

MongoDb: Rename a property in a complex document

We have documents saving to MongoDb. The problem is that one of our sub-documents has an Id property that is getting returned as _id, which is causing serialize/deserialize issues with the C# driver due to how it interprets Id fields (see http://mongodb.github.io/mongo-csharp-driver/2.0/reference/bson/mapping/)
I would like to rename the property from Id to SetId, but our data is fairly dynamic and simple field rename solutions that I've seen elsewhere do not apply. Here's an example of some heavily edited simple data:
{
"Id": "5a6238dbccf20b38b0db6cf2",
"Title": "Simple Document",
"Layout": {
"Name": "Simple Document Layout",
"Tabs": [
{
"Name": "Tab1",
"Sections": [
{
"Name": "Tab1-Section1",
"Sets": [
{
"Id": 1
}
]
}
]
}
]
}
}
Compare with more complex data:
{
"Id": "5a6238dbccf20b38b0db6abc",
"Title": "Complex Document",
"Layout": {
"Name": "Complex Document Layout",
"Tabs": [
{
"Name": "Tab1",
"Sections": [
{
"Name": "Tab1-Section1",
"Sets": [
{
"Id": 1
}
]
},
{
"Name": "Tab1-Section2",
"Sets": [
{
"Id": 1
}
]
}
]
},
{
"Name": "Tab2",
"Sections": [
{
"Name": "Tab2-Section1",
"Sets": [
{
"Id": 1
}
]
}
]
},
{
"Name": "Tab3",
"Sections": [
{
"Name": "Tab3-Section1",
"Sets": [
{
"Id": 1
},
{
"Id": 2
}
]
}
]
}
]
}
}
Note that the Set.Id field can be on multiple tabs on multiple sections with multiple sets. I just don't know how to approach a query to handle renaming data at all these levels.
I took #Veerum's advice and did a manual iteration over the collection with something like this:
myCol = db.getCollection('myCol');
myCol.find({ "Layout.Tabs.Sections.Sets._id": {$exists: true} }).forEach(function(note) {
for(tab = 0; tab != note.Layout.Tabs.length; ++tab) {
for(section = 0; section != note.Layout.Tabs[tab].Sections.length; ++section) {
for(set = 0; set != note.Layout.Tabs[tab].Sections[section].Sets.length; ++set) {
note.Layout.Tabs[tab].Sections[section].Sets[set].SetId = NumberInt(note.Layout.Tabs[tab].Sections[section].Sets[set]._id);
delete note.Layout.Tabs[tab].Sections[section].Sets[set]._id
}
}
}
myCol.update({ _id: note._id }, note);
});
Perhaps there is a more efficient way, but we are still on Mongo v3.2 and it seems to work well.

Parsing LuisResult to get values field

I have a LuisResult variable called result that has JSON info like
{
"query": "what is twenty * three",
"topScoringIntent": {
"intent": "Multiplication",
"score": 0.740870655
},
"intents": [
{
"intent": "Multiplication",
"score": 0.740870655
},
{
"intent": "Subtraction",
"score": 0.04339512
},
{
"intent": "None",
"score": 0.0164503977
},
{
"intent": "addition",
"score": 0.0126439808
},
{
"intent": "Division",
"score": 0.0108866822
}
],
"entities": [
{
"entity": "twenty",
"type": "builtin.number",
"startIndex": 8,
"endIndex": 13,
"resolution": {
"value": "20"
}
},
{
"entity": "three",
"type": "builtin.number",
"startIndex": 17,
"endIndex": 21,
"resolution": {
"value": "3"
}
}
]
}
I'm trying to access the "value" field under "resolution" since it converts string representations of numbers to digit representation. At the moment I'm just trying to get the first value. I've tried to extract the value this way
var valuesEntity = result.Entities; //IList of all entities
string s = "";
s = valuesEntity[i].Resolution.Values.ToString(); //extract value field??
await context.PostAsync($"{s}"); //post to emulator
This prints out System.Collections.Generic.Dictionary`2+ValueCollection[System.String,System.String]
to me. What am I missing to be able to get the "values" field?
Try
valuesEntity[i].Resolution.Values[0].ToString();
Values is a collection of strings.
You can also use linq and do:
valuesEntity[i].Resolution.Values.FirstOrDefault();

Handling double quotes in JSON strings

We have an application with knockout and we are facing a problem that some registers in the database have double quotes, which caused JSON parsing to fail.
Here's my json that is not valid due to a rogue double quote:
{
"OptionSummaries": [
{
"Id": 110,
"Name": "Option 1",
"Status": 1,
"ProductGroupNodes": [
{
"Id": 110,
"Name": "Corporate Brand Reputation",
"Status": 2,
"Waves": [
{
"Id": 110,
"Name": "Wave 1",
"Status": 2,
"Services": [
{
"Id": 1101,
"Title": "Proposal Budget Owner Service",
"CurrencyCode": "USD",
"EstimatedCost": 177.0000,
"CreationDateTime": "/Date(1437472898503)/",
"Status": 2
}
]
}
]
},
{
"Id": 111,
"Name": "2013 Consumer Scan",
"Status": 1,
"Waves": [
{
"Id": 111,
"Name": "Wave 1",
"Status": 1,
"Services": [
{
"Id": 1111,
"Title": "Proposal Budget Owner Service",
"CurrencyCode": "USD",
"EstimatedCost": 0.0000,
"CreationDateTime": "/Date(1437472898503)/",
"Status": 1
}
]
}
]
}
]
},
{
"Id": 115,
"Name": "Option 2",
"Status": 1,
"ProductGroupNodes": [
{
"Id": 115,
"Name": "Corporate Brand Reputation",
"Status": 1,
"Waves": [
{
"Id": 115,
"Name": "Wave 1",
"Status": 1,
"Services": [
{
"Id": 1151,
"Title": "Proposal Budget Owner Service",
"CurrencyCode": "USD",
"EstimatedCost": 0.0000,
"CreationDateTime": "/Date(1437472898503)/",
"Status": 1
}
]
}
]
},
{
"Id": 116,
"Name": "2013 Consumer Scan",
"Status": 1,
"Waves": [
{
"Id": 116,
"Name": "Wave 1",
"Status": 1,
"Services": [
{
"Id": 1161,
"Title": "Proposal Budget Owner Service",
"CurrencyCode": "USD",
"EstimatedCost": 0.0000,
"CreationDateTime": "/Date(1437472898503)/",
"Status": 1
}
]
}
]
}
]
}
],
"ServiceCostsEdit": {
"ServiceId": 1101,
"ServiceName": "Proposal Budget Owner Service",
"ServiceCurrencyIsoCode": "USD",
"ServiceLegalEntityCode": "0310",
"LaborHourCostsPanel": {
"LaborHourCosts": [
{
"Id": 2,
"CostCenters": [
{
"Disabled": false,
"Group": null,
"Selected": false,
"Text": "3101010001 - Consumer KAM Group",
"Value": "3101010001"
},
{
"Disabled": false,
"Group": null,
"Selected": false,
"Text": "3102510255 - Knowledge Panel",
"Value": "3102510255"
}
],
"FiscalYears": [
{
"Disabled": false,
"Group": null,
"Selected": false,
"Text": "2013",
"Value": "2013"
}
],
"LaborGrades": [
{
"Code": "0HL002",
"CurrencyCode": "USD",
"Rate": 44.0000,
"Disabled": false,
"Group": null,
"Selected": false,
"Text": "0HL002 - 44.00/hr USD",
"Value": "0HL002"
}
],
"SelectedLaborGradeCostCenter": "3101010001",
"SelectedLaborGradeFiscalYear": 2013,
"SelectedLaborGradeCode": "0HL002",
"SelectedLaborGradeRate": 44.0000,
"SetupHours": 2.00,
"ManagementHours": 1.00,
"DeliveryHours": 1.00,
"IsEmpty": false
}
],
"LaborHourCostsCostCenterDataSource": [
{
"Disabled": false,
"Group": null,
"Selected": false,
"Text": "3101010001 - Consumer KAM Group",
"Value": "3101010001"
},
{
"Disabled": false,
"Group": null,
"Selected": false,
"Text": "3102510255 - Knowledge Panel",
"Value": "3102510255"
}
],
"DefaultCostCenterCodeForInitialEmptyRecord": null,
"DefaultFiscalYearForInitialEmptyRecord": null,
"OverheadCosts": [
{
"LaborGradeCostCenterCode": "3101010001",
"LaborGradeFiscalYear": 2013,
"OverheadRate": 0.0000,
"SetupHours": 2.00,
"ManagementHours": 1.00,
"DeliveryHours": 1.00
}
],
"OverheadCostsVisible": true,
"OverheadCostsInitialDataSource": [
{
"Key": {
"CostCenterCode": "3101010001",
"FiscalYear": 2013
},
"Value": {
"Code": "0HO001",
"CurrencyCode": "USD",
"Rate": 0.00,
"Disabled": false,
"Group": null,
"Selected": false,
"Text": "0HO001 - USD 0.00/hr",
"Value": "0HO001"
}
}
],
"CostCenter": "F2F PAPI",
"ServiceCurrencyIsoCode": "USD",
"EditingAllowed": true
},
"VendorCostsPanel": {
"VendorCosts": [
{
"Id": 132,
"SelectedCostElementCode": "1992000004",
"VendorCode": "",
"VendorName": null,
"Description": "doublequotes"","DirectCostAttachment":null,"Quantity":1,"VendorRate":1.0000,"IsEmpty":false}],"CostElements":[{"Disabled":false,"Group":null,"Selected":false,"Text":"ExternalSuppliercosts","Value":"1992000004"},{"Disabled":false,"Group":null,"Selected":false,"Text":"Licensesfromaffilitatedcompanies","Value":"1992000002"}],"ServiceCurrencyIsoCode":"USD","EditingAllowed":true},"CostingAssumptionsPanel":{"Description":"","EditingAllowed":true},"ServiceSpecificationsPanel":{"Title":"ProposalBudgetOwnerService","Type":"ProposalBudgetOwnerService","Fields":[{"Value":"Hellolonglonglongtext...","Id":153,"Code":"OVERVIEW","Title":"Overview","IsRequiredForCosting":false,"DependencyVisibilityExpression":null,"FieldCodesToReevaluateOnChange":[],"EditingAllowed":false}]},"ApprovalComments":{"CommentType":0,"Message":null,"ApproverName":null,"ApproverEmail":null,"AnyComments":false},"RejectedCostInfoVisible":false,"EditingAllowed":true},"SubmitCostsEnabled":true,"EditingAllowed":false,"SelectedTreeNode":{"Id":1101,"Type":3},"Proposal":{"ProposalId":11,"ProposalName":"Ad-hocatCostingonMain","ProposalCostCenterCode":"3102510220","ProposalValid":{"IsValid":true,"ErrorMessage":""},"SoldToCustomer":"JenniferSamson","ExpectedProjectStartDate":"/Date(1426892400000)/","ExpectedProjectEndDate":"/Date(1431208800000)/","FunctionalityAreaEnabled":true}}
If you test this json against jsonlint you will see where the problem lies. What is the best way to handle this? I think the way I'm serializing the C# model to JSON is not proper? To do that I use:
var jsonModel = JsonConvert.SerializeObject(Model);
Any help is very appreciated.
EDIT
Issue was fixed. Problem was with the serialization.
I fixed this by using the method HttpUtility.JavaScriptStringEncode
var jsonViewModel = HttpUtility.JavaScriptStringEncode(Json.Encode(Model));
This solved my problem. All I had to do to pass this to knockout was #Html.Raw(jsonViewModel)
Best regards and thanks everyone!
Daniel

JToken get a specific value

I have following JToken output. How can I retrieve the 'value' here from TenantID which should be 1 in this case?
{[
{
"value": 1,
"metadata": {
"userType": 0,
"flags": 8,
"type": {
"type": "INT4",
"name": "Int",
"id": 56
},
"colName": "TenantID"
}
}
]}
This is my current code :
JToken value;
if (usr.Profile.TryGetValue("tenantid", out value))
{
JObject inner = value["value"].Value<JObject>(); //not working with null error
User.TenantID = (string)value;
}
User.obj = usr.Profile;
EDIT - please find below the complete JToken output :
{[
{
"value": 1,
"metadata": {
"userType": 0,
"flags": 8,
"type": {
"type": "INT4",
"name": "Int",
"id": 56
},
"colName": "TenantID"
}
}
]}
Count: 1
First (Newtonsoft.Json.Linq.JContainer): {{
"value": 1,
"metadata": {
"userType": 0,
"flags": 8,
"type": {
"type": "INT4",
"name": "Int",
"id": 56
},
"colName": "TenantID"
}
}}
First (Newtonsoft.Json.Linq.JToken): {{
"value": 1,
"metadata": {
"userType": 0,
"flags": 8,
"type": {
"type": "INT4",
"name": "Int",
"id": 56
},
"colName": "TenantID"
}
}}
HasValues: true
IsReadOnly: false
Last (Newtonsoft.Json.Linq.JContainer): {{
`"value": 1,
"metadata": {
"userType": 0,
"flags": 8,
"type": {
"type": "INT4",
"name": "Int",
"id": 56
},
"colName": "TenantID"
}
}}
Last (Newtonsoft.Json.Linq.JToken): {{
"value": 1,
"metadata": {
"userType": 0,
"flags": 8,
"type": {
"type": "INT4",
"name": "Int",
"id": 56
},
"colName": "TenantID"
}
}}
Next: (null)
Parent: {"tenantid": [
{
"value": 1,
"metadata": {
"userType": 0,
"flags": 8,
"type": {
"type": "INT4",
"name": "Int",
"id": 56
},
"colName": "TenantID"
}
}
]}
Path: "tenantid"
Previous: (null)
Static members:
Non-public members:
IEnumerator:
Root: {{
"name": "Rx Sidhu",
"given_name": "Rx",
"family_name": "Sidhu",
"locale": "en_US",
"emails": [
"ranxdeep#xxx.com",
"ranxdeep#xxx.com",
"ranxdeep#hx.com"
],
"nickname": "ranxdeep#xxx.com",
"email": "ranxdeep#xxx.com",
"picture": "https://apis.live.net/v5.0/f1xxxxxx/picture",
"roles": [
"Account Admin",
"Admin"
],
"tenantid": [
{
"value": 1,
"metadata": {
"userType": 0,
"flags": 8,
"type": {
"type": "INT4",
"name": "Int",
"id": 56
},
"colName": "TenantID"
}
}
],
"email_verified": true,
"clientID": "wxxxvC8",
"updated_at": "2015-07-15T16:26:30.526Z",
"user_id": "windowslive|f1axxxac",
"identities": [
{
"access_token": "EwBwAq1",
"provider": "windowslive",
"user_id": "f1aexxxxxac",
"connection": "windowslive",
"isSocial": true
}
],
"created_at": "2015-07-01T06:08:21.358Z"
}}
Type: 2
I need to check if the tenantID actually exists and then get value, else return null or 0.
You should be able to do:
JObject jObject = JObject.Parse(...);
JToken value = jObject.SelectToken("value");
You parse your object, then the inner contents should be exposed in which you can leverage the SelectToken method to find that specific value.
To build it out a bit, you could potentially do:
public static JToken FindToken<T>(string key, T value)
{
string serialized = NewtonsoftJsonSerializer.Instance.Serialize(value);
var jObject = JObject.Parse(serialized);
var jToken = jObject.SelectToken(key);
if(jToken != null)
return jToken;
return null;
}
I still cannot get the overall picture of your JSON, though have a look at this. It may help you.
var str = #"{
""x"": [{
""value"": 1,
""metadata"": {
""userType"": 0,
""flags"": 8,
""type"": {
""type"":""INT4"",
""name"":""Int"",
""id"": 56
},
""colName"":""TenantID""
}
}
]
}";
var parentJObject = JObject.Parse(str);
var xJArray = (JArray)parentJObject["x"];
// first item in JArray which is the object of interest
// look for the appropriate index of the JObject of your data
var firstJTokenInxJArray = (JObject)xJArray[0];
Console.WriteLine(firstJTokenInxJArray["value"].ToString());
I got what I was looking for :
JToken value;
if (usr.Profile.TryGetValue("tenantid", out value))
{
User.TenantID = (int)value [0] ["value"];
}

Categories