How can I list all my "children" elements recursively using the select token method?
Actual JSON Structure
{
"component": "stackpanel",
"id": "001",
"children": [
{
"component": "label",
"id": "001.1",
"text": "foobar123",
"children": []
},
{
"component": "textbox",
"id": "001.2",
"text": "",
"children": []
},
{
"component": "stackpanel",
"id": "001.3",
"children": [
{
"component": "textbox",
"id": "001.3.1",
"text": "subfoobar",
"children": []
}
]
}
]
}
My code Implementation
var listChildrenElements= jsonElement.SelectTokens("$..*").OfType<JObject>();
Result I wait for the select token:
[
{
"component": "stackpanel",
"id": "001",
"children": [...]
},
{
"component": "label",
"id": "001.1",
"text": "foobar123",
"children": []
},
{
"component": "textbox",
"id": "001.2",
"text": "",
"children": []
},
{
"component": "stackpanel",
"id": "001.3",
"children": [...]
},
{
"component": "textbox",
"id": "001.3.1",
"text": "subfoobar",
"children": []
}
]
Is it possible to make the list according to the expected model example that I hope to receive? This in a recursive way because there can be numerous elements within the "children"
Try this:
public static IEnumerable<JObject> SelectHierarchy(IEnumerable<JObject> source)
{
foreach (var item in source)
{
yield return item;
var childResults = SelectHierarchy(item["children"].Children().Cast<JObject>());
foreach (var childItem in childResults)
{
yield return childItem;
}
}
}
Then call it on IEnumerable with your root item:
var list = SelectHierarchy(new [] {jobject});
Related
We have json format as shown below and want to normalize it as given in expected output.
Input format:
[
{
"country": "Germany",
"name": "2010",
"value": 40632
},
{
"country": "United States",
"name": "2010",
"value": 0
},
{
"country": "United States",
"name": "2000",
"value": 45986
},
{
"country": "United States",
"name": "1990",
"value": 37060
},
{
"country": "France",
"name": "2010",
"value": 36745
},
{
"country": "France",
"name": "2000",
"value": 34774
}
]
Expected output :
[
{
"name": "Germany",
"series": [
{
"name": "2010",
"value": 40632
}
]
},
{
"name": "United States",
"series": [
{
"name": "2010",
"value": 0
},
{
"name": "2000",
"value": 45986
},
{
"name": "1990",
"value": 37060
}
]
},
{
"name": "France",
"series": [
{
"name": "2010",
"value": 36745
},
{
"name": "2000",
"value": 34774
}
]
}
]
try this
var jArr = JArray.Parse(input);
var groupedData = jArr.GroupBy(a => a["country"]).ToList();
var outputArr = new JArray();
foreach (var item in groupedData)
{
JObject obj = new JObject();
obj.Add("name", item.Key);
var arr = new JArray();
obj.Add("series", arr);
foreach (var jObj in item)
{
JObject newObj = new JObject();
newObj.Add("name", jObj["name"]);
newObj.Add("value", jObj["value"]);
arr.Add(newObj);
}
outputArr.Add(obj);
}
var output = outputArr.ToString();
I want to get the FILE-file-id, FILE-fileSize FILENAME-id, INCIDENT-reportedOn out of the following JObject:
Note the two "[[" at the beginning. Do I have to reduce the JObject first?
[
[{
"FILENAME": {
"id": "renamedtopdf.docx.pdf",
"label": "fileName",
"type": "vertex"
},
"FILE": {
"id": "dc92d48b7e29c528b3eb168446e51736101122a821c9e712320bd6842116719a",
"label": "file",
"type": "vertex",
"properties": {
"fileSize": [{
"id": "f9339436-189a-4503-abc6-e2989be6f138",
"value": "164198"
}],
"mimeType": [{
"id": "0a89dbfa-c204-45c8-8524-3fbd02b04e39",
"value": "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"
}]
}
},
"INCIDENT": {
"id": "16ea8c8b-65ee-44b3-afbb-98308b092b4f",
"label": "incident",
"type": "vertex",
"properties": {
"reportedOn": [{
"id": "81485296-a62f-4d17-a03f-4995c3cad937",
"value": "2/16/2019 10:33:59 AM"
}]
}
}
},
I'll assume you already extracted the JObject from the two arrays. I that case you can simply use the index operator to traverse the json file like so:
json["FILE"]["id"].Value<string>();
json["FILE"]["properties"]["fileSize"]["value"].Value<string>();
json["FILENAME"]["id"].Value<string>();
json["INCIDENT"]["properties"]["reportedOn"]["Value"].Value<string>();
Full Example:
const string text = #"{
"FILENAME": {
"id": "renamedtopdf.docx.pdf",
"label": "fileName",
"type": "vertex"
},
"FILE": {
"id": "dc92d48b7e29c528b3eb168446e51736101122a821c9e712320bd6842116719a",
"label": "file",
"type": "vertex",
"properties": {
"fileSize": [
{
"id": "f9339436-189a-4503-abc6-e2989be6f138",
"value": "164198"
}
],
"mimeType": [
{
"id": "0a89dbfa-c204-45c8-8524-3fbd02b04e39",
"value": "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"
}
]
}
},
"INCIDENT": {
"id": "16ea8c8b-65ee-44b3-afbb-98308b092b4f",
"label": "incident",
"type": "vertex",
"properties": {
"reportedOn": [
{
"id": "81485296-a62f-4d17-a03f-4995c3cad937",
"value": "2/16/2019 10:33:59 AM"
}
]
}
}
}";
var json = JObject.Parse(text);
json["FILE"]["id"].Value<string>();
json["FILE"]["properties"]["fileSize"]["value"].Value<string>();
json["FILENAME"]["id"].Value<string>();
json["INCIDENT"]["properties"]["reportedOn"]["Value"].Value<string>();
I have a JArray of JArrays, but I would like to flatten it into a single JArray of JObjects. I have already implemented a foreach loop which iterates through each JArray in my JArray. I need to know how to flatten each sub-JArray into a JObject.
Here is an example:
[
{
"item": [
{
"fieldName": "Name",
"value": "Andy"
},
{
"fieldName": "Phone",
"value": "678-905-9872"
}
]
},
{
"item": [
{
"fieldName": "Name",
"value": "John"
},
{
"fieldName": "Phone",
"value": "688-954-5678"
}
]
},
{
"item": [
{
"fieldName": "Name",
"value": "Ashley"
},
{
"fieldName": "Phone",
"value": "+44 671 542 8945"
}
]
},
{
"item": [
{
"fieldName": "Name",
"value": "Avi"
},
{
"fieldName": "Phone",
"value": "(212)-908-7772"
}
]
}
]
I would like each item to be a single JObject, resulting in the following JArray:
[
{
"Name": "Andy"
"Phone": "678-905-9872"
},
{
"Name": "John"
"Phone": "688-954-5678"
{
"Name": "Ashley"
"Phone": "+44 671 542 8945"
},
{
"Name": "Avi"
"Phone": "(212)-908-7772"
}
]
Thanks!
EDIT
Here is my solution (c#, using Newtonsoft.Json)
public string ParserFunction(string json)
{
string fieldname, fieldvalue;
JArray jsonArray = JArray.Parse(json);
foreach (JObject item in jsonArray)
{
JArray temp = (JArray)item["columns"]; //create new temporary JArray
foreach (JObject jobject in temp)
{
fieldname = jobject["fieldName"].ToString();
fieldvalue = jobject["value"].ToString();
item.Add(fieldname, fieldvalue);
jobject.Remove("fieldName");
jobject.Remove("value");
}
item.Remove("item");
}
json = jsonArray.ToString();
return json;
}
Not sure if this is the most optimal way to do it, I saw an answer below which looks alright as well.
var jArr = new JArray(JArray.Parse(JSON)
.Select(x => new JObject(new JProperty("Name", x["item"][0]["Name"]),
new JProperty("Phone", x["item"][1]["Phone"])
)
)
);
var str = JsonConvert.SerializeObject(jArr, Formatting.Indented);
str would be:
[
{
"Name": "Andy",
"Phone": "(785) 241-6200"
},
{
"Name": "Arthur Song",
"Phone": "(212) 842-5500"
},
{
"Name": "Ashley James",
"Phone": "+44 191 4956203"
},
{
"Name": "Avi Green",
"Phone": "(212) 842-5500"
}
]
Lets see, the json can be dynamic and can probably have number of nested arrays within any property.
Example:
{
"items": [
{
"id": "0001",
"name": "Cake",
"batters": {
"batter": [
{
"id": "1001",
"type": "Regular"
},
{
"id": "1002",
"type": "Chocolate"
},
{
"dry": [
{
"id": "1003",
"type": "Devil's Food"
}
]
}
],
"other": [
{
"id": "1004",
"type": "Home Food"
}
]
},
"topping": [
{
"id": "5002",
"type": "Glazed"
},
{
"id": "5005",
"type": "Sugar"
}
]
},
{
"id": "0002",
"name": "Sweets"
}
]
}
A simple list should return elements as:
[
{
"id": "1001",
"type": "Regular"
},
{
"id": "1002",
"type": "Chocolate"
},
{
"id": "1003",
"type": "Devil's Food"
},
{
"id": "1004",
"type": "Home Food"
},
{
"id": "5002",
"type": "Glazed"
},
{
"id": "5005",
"type": "Sugar"
},
{
"id": "0002",
"name": "Sweets"
}
]
Please note:
Json can by anything, no property can be used for extraction , just knowing that what needed is stuff inside an JArray.
What i have tried so far but its just a start:
public static bool ParseJsonArray(JToken token, List<string> extracts, string parentLocation = "")
{
if (token.HasValues)
{
foreach (JToken child in token.Children())
{
if (token.Type == JTokenType.Array)
{
parentLocation += ((JProperty)token).Name;
extracts.Add(token.ToString());
}
ParseJsonArray(child, extracts, parentLocation);
}
return true;
}
else
{
return false;
}
}
token here is the parsed dynamic json.
It appears as though you want to recursively find all JArray entries that do not themselves contain nested arrays. Let's call these "leaf" array entries. I say that because you don't include the following non-leaf entry in your results:
{
"id": "0001",
"name": "Cake"
}
That being said, you can find leaf array entries with the following extension method:
public static class JsonExtensions
{
public static IEnumerable<JToken> LeafArrayEntries(this JContainer container)
{
var nonLeafEntries = new HashSet<JToken>(container.DescendantsAndSelf()
.OfType<JArray>()
.SelectMany(a => a.Ancestors().Where(p => p.Type != JTokenType.Property)));
return container.DescendantsAndSelf().Where(c => c.Parent is JArray && !nonLeafEntries.Contains(c));
}
}
Then put the returned items in an array of their own with:
var leafItemArray = new JArray(rootJContainer.LeafArrayEntries());
i have json data, which is coming from an API. the structure of json is like this
{
"data": [
{
"nameid": "s_10",
"size": "6.46",
"name": "abc",
"children": [
{
"nameid": "i_101010",
"size": "8.84",
"name": "bcd",
"children": [
{
"nameid": "si_10101010",
"size": "4.00",
"name": "efg",
"children": [
{
"nameid": "c_3273",
"size": 4,
"name": "ttt",
}
]
},
{
"nameid": "si_10101020",
"size": "13.67",
"name": "sss",
"children": [
{
"nameid": "c_4450",
"size": 1,
"name": "rrr",
},
{
"nameid": "c_551",
"size": 17,
"name": "ddd",
},
i need to convert it to something like the below structure
{
"id": 1,
"parentId": "NULL",
"name": "Root",
"size": 5,
"children": [
{
"id": 10,
"parentId": "1",
"name": "En",
"size": 1,
"children": [
{
"id": 1010,
"parentId": "10",
"name": "Eee",
"size": 1,
"children": [
{
"id": 101010,
"parentId": "1010",
"name": "Enh",
"size": 5,
"children": [
{
"id": 10101010,
"parentId": "101010",
"name": "Ooo",
"size": 5
},
so in short, i need to add that field parent id to the first JSON
note: these are partial data, so json may not be a valid one.
If your source and destination object are Typed Class (e.g. public class FamilyMembers)
Automapper is the best way to achieve this.
http://automapper.org/
Let's say your source 'data" is class Families. You can map Families to FamilyMembers
//specify source, destination
Mapper.CreateMap<Families, FamilyMembers>();
//get source data
Families families = GetFamiliesFromAPI();
//map each properties of families to familymembers
FamilyMembers familymembers = Mapper.Map<Families, FamilyMembers>(families);
ShowFamilyMembersInDataGrid(familymembers);
If you don't want to use Automapper, then go with LINQ
Families families = GetFamiliesFromAPI();
families.Select(f => f, new FamilyMembers() {name = f.Name, someProperty = f.someProperty }
Since you have nested JSON object you need to learn how to handle such as "children" member in your source data and map if via LINQ accordingly