JObject parse returns extra curly braces - c#

I have a variable projectData that contains a valid json string that is stored in a database.
After doing the following:
JObject obj = new JObject();
obj = JObject.Parse(projectData);
Instead of getting
{
"devices": {
"device_A": {
"id": "12345",
"name": "test",
"enabled": true
}
}
}
I get this instead:
{{
"devices": {
"device_A": {
"id": "12345",
"name": "test",
"enabled": true
}
}
}}
So basically an aditional { and } were added to my json string.
I have also tried the following:
obj = JsonConvert.DeserializeObject<JObject>(projectData);
and it didnt work.
Why is this a problem to me?
I want to iterate over the obj["devices"] array, and when I do the following
foreach(var d in obj["devices"])
It simply doesnt work because of the double curly braces.
Is there a solution to my problem?
Thank you

{
"devices": {
"device_A": {
"id": "12345",
"name": "test",
"enabled": true
}
}
}
Your json shows devices as a json object and not an array. You cannot iterate over it with a for loop.
You can access the data by parsing it first and then accessing the properties by using the [] brackets.
var obj = JObject.Parse(jsonString);
Console.WriteLine(obj["devices"]["device_A"]["id"].Value<string>());
//prints
12345
// To Loop through multiple devices... you can use this.
foreach (var device in ((JObject)obj["devices"]).Properties())
Console.WriteLine(obj["devices"][device.Name]["id"]);
Also, when you are using the debug mode, the watch or locals will show {{ }} because the braces are escaped.
Array version of Json
If your json looked like below, then you can use the for loop to access the elements of the JArray.
{
"devices": [
{
"device_A": {
"id": "12345",
"name": "test",
"enabled": true
}
}
]
}
with the above json, you can use the for loop in the following way,
var obj = JObject.Parse(json);
foreach (var device in obj["devices"])
Console.WriteLine(device["device_A"]["id"]);
// Prints
12345

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;

How to remove parent element from json in c#

How to covert the below json
{"data":{"id":12,"name":"jeremy","email":"jeremy#test.com"}}
to
{"id":12,"name":"jeremy","email":"jeremy#test.com"}
I want to remove the "data" element from json.
With json.net it's fairly straightforward
var input = "{\"data\":{\"id\":12,\"name\":\"jeremy\",\"email\":\"jeremy#test.com\"}}";
var result = JObject.Parse(input)["data"].ToString(Formatting.None);
Console.WriteLine(result);
Note : Formatting.None is only to preserve the formatting you had in your original example
Or Text.Json
var result = JsonDocument.Parse(input).RootElement.GetProperty("data").ToString();
Output
{"id":12,"name":"jeremy","email":"jeremy#test.com"}
Additional Resources
JObject.Parse Method (String)
Load a JObject from a string that contains JSON.
JObject.Item Property (String)
Gets or sets the JToken with the specified property name.
JToken.ToString Method (Formatting,JsonConverter[])
Returns the JSON for this token using the given formatting and
converters.
Formatting Enumeration
None 0 No special formatting is applied.
Text.Json
JsonDocument.Parse Method
Provides a mechanism for examining the structural content of a JSON
value without automatically instantiating data values.
JsonDocument.RootElement Property
Gets the root element of this JSON document
JsonElement.GetProperty Method
Gets a JsonElement representing the value of a required property
identified by propertyName.
I have a follow up question on a scenario where I don't want to remove the root element.
{
"keepMe": {
"removeMe": [
{
"id": "1",
"name": "Foo",
"email": "Foo#email.com"
},
{
"id": "2",
"name": "Bar",
"email": "Bar#email.com"
}
]
}
But I wanted it to look like
{
"keepMe": {
{
"id": "1",
"name": "Foo",
"email": "Foo#email.com"
},
{
"id": "2",
"name": "Bar",
"email": "Bar#email.com"
}
}
Using below would not work. Is there another way to do this?
var result = JObject.Parse(input)["keepMe"]["removeMe"].ToString(Formatting.None);
//{
// "id": "1",
// "name": "Foo",
// "email": "Foo#email.com"
//},
//{
// "id": "2",
// "name": "Bar",
// "email": "Bar#email.com"
//}
var result = JObject.Parse(input)["removeMe"].ToString(Formatting.None); //Null Reference
Found the answer using the SelectToken and Replace keyword
var jObj = JObject.Parse(input);
jObj.SelectToken("keepMe").Replace(jObj.SelectToken("keepMe.removeMe"));
string result = jObj.ToString();

Given a JSON value, how do I get the parent's sibling value?

I have a .NET Core 3.1 C# application reading the following JSON doc:
{
"info": {
"_postman_id": "b"
},
"item": [
{
"name": "GetEntityById via APIM",
"item": [
{
"name": "Call 1",
"url": {
"raw": "urlforcall1"
}
},
{
"name": "Call 2",
"url": {
"raw": "urlforcall2"
}
}
]
}
]
}
I want to select the value for each item\item\name and each item\item\url\raw.
So, I'd like to end up with "Call 1":"urlforcall1" and "Call 2":"urlforcall2".
I've been playing around and can grab the value from the raw token with the following:
var jObject = JObject.Parse(jsonString);
var urls = jObject.SelectTokens("..raw");
How can I grab the value from its parent's sibling, name?
I hope this code will help you
using Newtonsoft.Json.Linq;
using System;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
string json = #"
{
'info': {
'_postman_id': 'b'
},
'item': [
{
'name': 'GetEntityById via APIM',
'item': [
{
'name': 'Call 1',
'url': {
'raw': 'urlforcall1',
}
},
{
'name': 'Call 2',
'url': {
'raw': 'urlforcall2',
}
}
]
}
]
}";
dynamic d = JObject.Parse(json);
foreach(var item in d.item)
{
foreach(var innerItem in item.item)
{
Console.WriteLine($"'{innerItem.name}' : '{innerItem.url.raw}'");
}
}
}
}
}
Can be tested here https://dotnetfiddle.net/xDr90O
To answer your question directly, if you have a JToken you can navigate upward from there using the Parent property. In your case you would need to use it four times to get to the level you want:
The parent of the JValue representing the call URL string is a JProperty with the name raw
The parent of that JProperty is a JObject
The parent of that JObject is a JProperty with the name url
The parent of that JProperty is a JObject, which also contains the name property
From there you can navigate back down using indexer syntax to get the value of name.
So, you would end up with this:
var jObject = JObject.Parse(jsonString);
foreach (JToken raw in jObject.SelectTokens("..raw"))
{
string callName = (string)raw.Parent.Parent.Parent.Parent["name"];
string urlForCall = (string)raw;
}
You may flatten inner item array using SelectMany method into one sequence (since outer item is also an array), then get name and raw values directly by key
var jObject = JObject.Parse(jsonString);
var innerItems = jObject["item"]?.SelectMany(t => t["item"]);
foreach (var item in innerItems)
{
var name = item["name"];
var raw = item["url"]?["raw"];
}

Looping through JObject nested array

I can not figure out exactly how to did through this JObject in order to retrieve the id property under runs.
I have this following code which will successfully give me the id property that is under entries, but how can I nest this again to go into the runs sections and get those ID's?
JSON:
{
"id": 168,
"name": "section 1",
"entries": [
{
"id": "908-9876-908",
"suite_id": 15,
"name": "List 1",
"runs": [
{
"id": 169,
"suite_id": 15
}
]
},
{
"id": "998-4344-439",
"suite_id": 16,
"name": "List 2",
"runs": [
{
"id": 170,
"suite_id": 16
}
]
}
]
}
C# Code:
JObject obj = JsonConvert.DeserializeObject<JObject>(response);
foreach (JObject id in obj["entries"])
{
string returnable = (string)id["id"];
Console.WriteLine(returnable);
}
I have tried looking at ["entries"]["runs"] but that also was not working.
The print out of this is:
908-9876-908
998-4344-439
What I would like is
169
170
You can achieve it using the following code
var jsonObject = JObject.Parse(json);
foreach (var entry in jsonObject["entries"])
{
foreach (var run in entry["runs"])
{
string returnable = (string)run["id"];
Console.WriteLine(returnable);
}
}
You would like to see
169
170
They are an id values from runs array, therefore you should enumerate them in the inner loop. You've also missed a comma after "name": "section 1"
You can use SelectTokens() to query for nested data inside a JToken hierarchy. It provides support for JSONPath queries including wildcards [*] for arrays:
var ids = obj.SelectTokens("entries[*].runs[*].id").Select(i => (long)i).ToList();
See: Querying JSON with complex JSON Path.
Demo fiddle here.

JSON.NET reader problem

i got some problem when i generate .json file from spring .json ,and i got this format
{ "models": [
{
"id":1,
"modelName":"dfdsf",
"created":{
"userFullname":"demo",
"time":"150301",
"date":"20110208",
"userId":"123"
},
"remark":"dsfdf",
"updated":"~unique-id~1"
},
{
"id":2,
"modelName":"test",
"created":{
"userFullname":"test",
"time":"150301",
"date":"20110210",
"userId":"124"
},
"remark":"test",
"updated":{
"userFullname":"test",
"time":"150301",
"date":"20110209",
"userId":"test"
}
}
]}
first time i used JObject Parse for convert
JObject job = JObject.Parse(fullJson);
and the other hand i used jtoken to focus "models"
JToken jDetail = job["models"];
but the problem is {[{ xxx }]} it look like jarray i don't have any idea to convert it
i ever use JArray, JsonTextReader but it doesn't work.
could suggestion some? because if i pass this ll i set some value to object.
thank you for every idea.
string fullJson = File.ReadAllText("TextFile1.txt"); // for brevity
var job = JObject.Parse(fullJson);
var models = job.Value<JArray>("models");
Console.WriteLine(models[0]);
result:
{
"id": 1,
"modelName": "dfdsf",
"created": {
"userFullname": "demo",
"time": "150301",
"date": "20110208",
"userId": "123"
},
"remark": "dsfdf",
"updated": "~unique-id~1"
}

Categories