user6609534 user6609534 - 4 months ago 20
JSON Question

How can I generate all possible linq strings of a json object for Json.net?

In json.net we can using linq to json based on this tutorial

I want to know Is there anyway for generate string query or not ?

for example I have json like this :

{
"Name": "Test",
"Status": [
"S1",
"S2",
"S3",
"S4"
],
"People": [
{
"Name": "A",
"Family": "AA",
"Addresses": [
{
"Country": "A2",
"City": "A1",
"Phones": [
"A3",
"A4",
"A5"
]
}
]
},
{
"Name": "B",
"Family": "BB",
"Addresses": [
{
"Country": "B2",
"City": "B1",
"Phones": [
"B3",
"B4",
"B5"
]
}
]
},
{
"Name": "C",
"Family": "CC",
"Addresses": [
{
"Country": "C2",
"City": "C1",
"Phones": [
"C3",
"C4",
"C5"
]
},
{
"Country": "C7",
"City": "C6",
"Phones": [
"C8",
"C9",
"C10"
]
}
]
}
]
}


so I wrote all possible linq strings by hand :

// JSON.NET Linq Strings (by HAND)

"Name"
"Status[0]"
"Status[1]"
"Status[2]"
"Status[3]"
"People[0].Name"
"People[0].Family"
"People[0].Addresses[0].City"
"People[0].Addresses[0].Country"
"People[0].Addresses[0].Phones[0]"
"People[0].Addresses[0].Phones[1]"
"People[0].Addresses[0].Phones[2]"
"People[1].Name"
"People[1].Family"
"People[1].Addresses[0].City"
"People[1].Addresses[0].Country"
"People[1].Addresses[0].Phones[0]"
"People[1].Addresses[0].Phones[1]"
"People[1].Addresses[0].Phones[2]"
"People[2].Name"
"People[2].Family"
"People[2].Addresses[0].City"
"People[2].Addresses[0].Country"
"People[2].Addresses[0].Phones[0]"
"People[2].Addresses[0].Phones[1]"
"People[2].Addresses[0].Phones[2]"
"People[2].Addresses[1].City"
"People[2].Addresses[1].Country"
"People[2].Addresses[1].Phones[0]"
"People[2].Addresses[1].Phones[1]"
"People[2].Addresses[1].Phones[2]"


so I tried to write some codes for create all possible strings automatically

var dic = new Dictionary<string, string>();
var json = JsonConvert.SerializeObject(obj, new JsonSerializerSettings() { Formatting = Formatting.Indented });
JObject linq = JObject.Parse(json);
foreach (var x in linq) // DOES NOT WORK FOR CHILDS ?????!!!!!
{
string name = x.Key;
JToken value = x.Value;
if (value.HasValues) // Array
{
var counter = 0;
foreach (var item in value.Values())
{
dic.Add(name + $"[{counter}]", item.ToString());
counter++;
}
}
else // String
{
var v = value.ToString();
dic.Add(name, v);

}
}


but I dont know How can I write it for all childs that generate save above keys

dbc dbc
Answer

You can use SelectTokens("..*") to recursively descent the JSON token hierarchy, where ".." is the JSONPath recursive descent operator and "*" is a wildcard matching anything. Then you can use JToken.Path as your dictionary key:

var dic = linq.SelectTokens("..*")
    .ToDictionary(t => t.Path, t => t.ToString());

Note this includes the root token. If you want to skip it, do:

var dic = linq.SelectTokens("..*")
    .Where(t => t != linq)
    .ToDictionary(t => t.Path, t => t.ToString());

You could also use JContainer.DescendantsAndSelf() or JContainer.Descendants() to do the recursive descent, filtering out all JProperty nodes for the same result:

var dic = linq.Descendants()
    .Where(t => t.Type != JTokenType.Property)
    .ToDictionary(t => t.Path, t => t.ToString());