How to access to all JProperties sub values in Json.net? - c#

I`m trying to pars a Json in my C# code with Json.NET.
I want to print the child of each token after the parent.
my JSON string is something like this(but very longer):
{
"type": "ExpressionStatement",
"expression": {
"type": "CallExpression",
"callee": {
"type": "FunctionExpression",
"id": null,
"params": [
{
"type": "Identifier",
"name": "E"
},
{
"type": "Identifier",
"name": "B"
}
]
}
}
}
and I`m trying this code for my purpose and in this first I check value of JProperties and if there was something starts with '[' I sub String it and parse it again other otherwise print that :(r is my Json string)
JObject a = JObject.Parse(r);
ArrayList ab= new ArrayList();
String reg=#"{[-a-zA-Z0-9_~,'"":\s]*}\s*,\s*{[-a-zA-Z0-9~,'"":\s]*}";
ab.Add(a);
for (int i = 0; i < ab.Count; i++ )
{
JObject d=ab[i] as JObject;
foreach (JProperty p in (d.Children()))
{
String val = p.Value.ToString();
if( val.StartsWith("[")){
val=val.Substring(2,val.Length-2);
if(Regex.Match(val,reg).Success)
{
String reg2 = #"},\s*{";
int num=Regex.Match(val,reg2).Index;
String val1 = val.Substring(0,num+1);
JObject newob = JObject.Parse(val1);
ab.Add(newob);
val = val.Substring(num+3);
newob = JObject.Parse(val);
ab.Add(newob);
}
if (!val.Equals("")) {
JObject newob=JObject.Parse(val);
ab.Add(newob);}
}
else if (val.StartsWith("{"))
{
if (!val.Equals(""))
{
JObject newob = JObject.Parse(val);
ab.Add(newob);
}
}
else
{
Console.WriteLine("value is: {0}", p.Value);
}
}
}
but there is always error for sub String....they always are incorrect!
could anyone help me? or offer me new way?
note:I don`t know the JSON string and it is every time different

Related

Error when trying to pass a string into a json object c# - Current JsonReader item is not an object

I am trying to pass my variable query as a Json object. So I saw online that one way to do so is by doing JObject.Parse(). I attempted to do so, but when debugging I noticed that .Parse() would create a "{" at the beginning and a "}" at the end of the contents of the variable query. So I then attempted to remove the first "{" and last "}" inside of query but whenever I would hit the JObject.Parse() line, it would throw an exception saying:
Error reading JObject from JsonReader. Current JsonReader item is not an object: String. Path '', line 1, position 6.
So I then attempted to use the code after query, but this would still give me the same error when I hit the next line that consisted of JObject.Parse():
if (query.Length > 2){
query = query.Substring(1, s.Length-2)
}
So then I saw online that another way to get around this error is to use the following, but it would not remove the first "{" and last "}".
query = query.TrimStart(new char[] { '{' }).TrimEnd(new char[] { '}' });
This is what my query consists of and what I tried to do to pass query as a json object:
var query = "{\"size\": 1000,\"query\": {\"bool\": {\"should\":[ {\"match\": { \"level\": \"Information\" } }, {\"match\": { \"level\": \"Error\" } } ], " +
"\"filter\": [ { \"range\": { \"#timestamp\": { \"gte\": \"2021-07-26T07:58:45.304-05:00\", \"lt\": \"2021-07-26T08:58:45.305-05:00\" } } } ]," +
"\"minimum_should_match\": 1 } } }";
query = query.TrimStart(new char[] { '{' }).TrimEnd(new char[] { '}' });
/* if (query.Length > 2){
query = query.Substring(1, s.Length-2)
} */
var jsonQuery = JObject.Parse(query);
How would I go about resolving the issue I am having that .Parse() is adding an extra { at the beginning and } and at the end.
Variable Query holds:
{"size": 1000,"query": {"bool": {"should":[ {"match": { "level": "Information" } }, {"match": { "level": "Error" } } ], "filter": [ { "range": { "#timestamp": { "gte": "2021-07-26T07:58:45.304-05:00", "lt": "2021-07-26T08:58:45.305-05:00" } } } ],"minimum_should_match": 1 } } }
Then jsonQuery holds:
{{ "size": 1000, "query": { "bool": { "should": [ { "match": { "level": "Information" } }, { "match": { "level": "Error" } } ], "filter": [ { "range": { "#timestamp": { "gte": "2021-07-26T07:58:45.304-05:00", "lt": "2021-07-26T08:58:45.305-05:00" } } } ], "minimum_should_match": 1 } }}}
If you look closely, .Parse() is adding a { at the beginning and adding another } at the end.
That double parentheses "issue" is just debugger display for JObject in Visual Studio. If you actually try to output JObject as a string, you'll get correct output.
static void Main(string[] args)
{
var query = "{\"size\": 1000,\"query\": {\"bool\": {\"should\":[ {\"match\": { \"level\": \"Information\" } }, {\"match\": { \"level\": \"Error\" } } ], " +
"\"filter\": [ { \"range\": { \"#timestamp\": { \"gte\": \"2021-07-26T07:58:45.304-05:00\", \"lt\": \"2021-07-26T08:58:45.305-05:00\" } } } ]," +
"\"minimum_should_match\": 1 } } }";
var jsonQuery = JObject.Parse(query);
Console.WriteLine(jsonQuery); // all good!
Console.ReadLine();
}
On the side note, I think it would be easier for you to test Elasticsearch with NEST and Elasticsearch.NET nuget packages.

iterate through JSON?

Can I Iterate (recursive) through this JSON?
My Problem are not the JObject rather the JArray.
This is a multi-nested JSON that I would like to go through and from which I would like to read the key and value separately.
{
"DataValid": 1,
"Identifier": "865263040394502",
"RecordType": "D",
"TypeD_data": {
"tStat": {
"lDistance": 545190,
"lUpTimeGps": 21074,
"lUpTimeGsm": 34700,
"lUpTimeMCU": 127387,
"lUpTimeSys": 4727445,
"lUpTimeInMotion": 66343
},
"header": {
"info": 16797,
"tTime": 1597039293,
"reason": 4398046511136,
"version": 1
},
"tAcc_bas": {
"sXRaw": 65,
"sYRaw": 67,
"sZRaw": 983,
"Status": 1,
"sMagnitude": 66
},
"tAcc_ext": null,
"tGeo_bas": {
"polycount": 0
},
"tGeo_ext": null,
"tGps_bas": {
"Status": 11,
"sSpeed": 79,
"sCourse": 321,
"fLatitude": 48.59036,
"sAltitude": 474,
"fLongitude": 11.56852
},
"tGsm_bas": {
"ta": 0,
"mcc": 0,
"mnc": 0,
"Status": 2,
"cellcount": 0
},
"tGsm_ext": null,
"tTele_ext": null,
"tTele_int": {
"Status": 16,
"sTmpMCU": 2061,
"sBatLevel": 50,
"sBatVoltage": 3346,
"sExtVoltage": 0
},
"tTele_chain": null
},
"DataIdentifier": "Pos",
"Timestamp_Received": 1597039264
}
above there is the JSON I want to iterate through.
My Code:
public void SetValue(JObject value, string valueName = "")
{
foreach (var p in value)
{
if (p.Value is JObject)
{
SetValue((JObject)p.Value, valueName + "/" + p.Key);
}
}
}
above there is my Code.
Thank you in advance for the help.
public List<string> GetFieldNames(dynamic input)
{
List<string> fieldNames = new List<string>();
try
{
// Deserialize the input json string to an object
input = Newtonsoft.Json.JsonConvert.DeserializeObject(input);
// Json Object could either contain an array or an object or just values
// For the field names, navigate to the root or the first element
input = input.Root ?? input.First ?? input;
if (input != null)
{
// Get to the first element in the array
bool isArray = true;
while (isArray)
{
input = input.First ?? input;
if (input.GetType() == typeof(Newtonsoft.Json.Linq.JObject) ||
input.GetType() == typeof(Newtonsoft.Json.Linq.JValue) ||
input == null)
isArray = false;
}
// check if the object is of type JObject.
// If yes, read the properties of that JObject
if (input.GetType() == typeof(Newtonsoft.Json.Linq.JObject))
{
// Create JObject from object
Newtonsoft.Json.Linq.JObject inputJson =
Newtonsoft.Json.Linq.JObject.FromObject(input);
// Read Properties
var properties = inputJson.Properties();
// Loop through all the properties of that JObject
foreach (var property in properties)
{
// Check if there are any sub-fields (nested)
// i.e. the value of any field is another JObject or another JArray
if (property.Value.GetType() == typeof(Newtonsoft.Json.Linq.JObject) ||
property.Value.GetType() == typeof(Newtonsoft.Json.Linq.JArray))
{
// If yes, enter the recursive loop to extract sub-field names
var subFields = GetFieldNames(property.Value.ToString());
if (subFields != null && subFields.Count() > 0)
{
// join sub-field names with field name
//(e.g. Field1.SubField1, Field1.SubField2, etc.)
fieldNames.AddRange(
subFields
.Select(n =>
string.IsNullOrEmpty(n) ? property.Name :
string.Format("{0}.{1}", property.Name, n)));
}
}
else
{
// If there are no sub-fields, the property name is the field name
fieldNames.Add(property.Name + " : " + (string)property.Value<JProperty>());
}
}
}
else
if (input.GetType() == typeof(Newtonsoft.Json.Linq.JValue))
{
// for direct values, there is no field name
fieldNames.Add(string.Empty);
}
}
}
catch
{
throw;
}
return fieldNames;
}

How to remove the attribute container from JSON in C#?

I have an issue with JSON that contains several elements, and I want to convert some JSON array of objects without the id that contain the element itself. Basically what I want is to convert this structure:
{
"SubscriptionStorages": {
"1": {
"Type": "subscriberstorage",
"SubscriberStorage_Id": 1,
"SubscriberStorage_AdminDescription": "JM Basic",
"SubscriberStorage_MaxStorage": 268435456000
},
"2": {
"Type": "subscriberstorage",
"SubscriberStorage_Id": 2,
"SubscriberStorage_AdminDescription": "JM Standard",
"SubscriberStorage_MaxStorage": 536870912000
}
}
}
to this structure:
{
"SubscriptionStorages": [
{
"Type": "subscriberstorage",
"SubscriberStorage_Id": 1,
"SubscriberStorage_AdminDescription": "JM Basic",
"SubscriberStorage_MaxStorage": 268435456000
},
{
"Type": "subscriberstorage",
"SubscriberStorage_Id": 2,
"SubscriberStorage_AdminDescription": "JM Standard",
"SubscriberStorage_MaxStorage": 536870912000
}
]
}
Is there any simple way to do it?
This is what I have so far, but it's not good...
What am I missing here?
List<string> items = new List<string>();
if (itemsList != null)
{
if (itemsList.Count > 0)
{
JToken outer = JToken.Parse(jsonBody);
foreach (JToken t in outer)
{
items.Add(t.ToString());
}
}
}
return items;
You can transform your JSON like this:
var jo = JObject.Parse(originalJson);
jo["SubscriptionStorages"] = new JArray(
jo["SubscriptionStorages"]
.Children<JProperty>()
.Select(jp => jp.Value)
);
var modifiedJson = jo.ToString();
Fiddle: https://dotnetfiddle.net/9sCx2M

Build a Property List from a JSON Object c#

I want to build the property list including property path of a json object.
I don't know the structure of the json or the keys that might be present. I'm after the keys at all levels (not the values of those keys).
{
"Primitive_1": "T1",
"Object_L1": {
"Object_L2": {
"Object_L3": {
"Object_L4": {
"Object_L5": {
"Object_L6": {
"Array_L7": [
{
"asdasdas": "SampleText1",
"WIDTH": "Width2"
},
{
"gh45gdfg": "SampleText2",
"WIDTH": "Width"
}
],
"12836hasvdkl": "SampleText3",
"WIDTH": "Width"
}
}
},
"712bedfabsmdo98": "SampleText4",
"WIDTH": "Width"
}
},
"ALIAS_ID": 1
},
"Primitive_2": "T2",
"Primitive_3": "T3",
"Primitive_4": "T4"
}
Desired output:
.Primitive_1 .Object_L1.Object_L2.Object_L3.Object_L4.Object_L5.Object_L6.Array_L7.0.asdasdas
.Object_L1.Object_L2.Object_L3.Object_L4.Object_L5.Object_L6.Array_L7.0.WIDTH
.Object_L1.Object_L2.Object_L3.Object_L4.Object_L5.Object_L6.Array_L7.1.gh45gdfg
.Object_L1.Object_L2.Object_L3.Object_L4.Object_L5.Object_L6.Array_L7.1.WIDTH
.Object_L1.Object_L2.Object_L3.Object_L4.Object_L5.Object_L6.12836hasvdkl
.Object_L1.Object_L2.Object_L3.Object_L4.Object_L5.Object_L6.WIDTH
.Object_L1.Object_L2.Object_L3.712bedfabsmdo98
.Object_L1.Object_L2.Object_L3.WIDTH
.Object_L1.ALIAS_ID
.Primitive_2
.Primitive_3
.Primitive_4
Having looked around I've gotten as far as the root nodes of the object. See fiddle (https://dotnetfiddle.net/wIl1Qw)
This seems to be relatively simple in JS (http://jsfiddle.net/alteraki/bt3zc1wt/) I've already reviewed several responses and I can't find a response in c# that solves this problem without knowing the keys in use (which I don't know)
Any help would be much appreciated.
Tree traversal algorithms are almost always recursive in nature.
As such, the following function does what you want:
private static IEnumerable<string> GetMembers(JToken jToken)
{
var members = new List<string>();
if (jToken is JObject)
{
var jObject = (JObject)jToken;
foreach (var prop in jObject.Properties())
{
if (prop.Value is JValue)
{
members.Add(prop.Name);
}
else
{
members.AddRange(GetMembers(prop.Value).Select(member => prop.Name + "." + member));
}
}
}
else if (jToken is JArray)
{
var jArray = (JArray)jToken;
for (var i = 0; i < jArray.Count; i++)
{
var token = jArray[i];
members.AddRange(GetMembers(token).Select(member => i + "." + member));
}
}
return members;
}
An example of the code running is available here.

Add nested code infinite times

I have a unique issue. My program is getting bookmarks from chrome, from a Bookmarks JSON file. I am using the JSON.net dll for this. My issue is, is that I need to get each URL in its correct folder hierarchy, however, it seems that you can create an infinate amount of folders to hold the bookmarks in. Here is an example of the JSON hiarchy:
{
"checksum": "c9e24e7fb3c6cb184fb776e32dd1004e",
"roots": {
"bookmark_bar": {
"children": [ {
{
"children": [ {
"children": [ {
"children": [ {
"children": [ {
"date_added": "12985566069697953",
"id": "225",
"name": "EvasiveURL",
"type": "url",
"url": "evasiveurl.com"
} ],
"date_added": "12991165233108137",
"date_modified": "12991165244676611",
"id": "374",
"name": "NestedFolder2",
"type": "folder"
} ],
"date_added": "12991165215985934",
"date_modified": "12991165215985934",
"id": "373",
"name": "NestedFolder",
"type": "folder"
} ],
"date_added": "12985566069695953",
"date_modified": "12991165219618934",
"id": "204",
"name": "Games",
"type": "folder"
}
And here is my current code:
for (int i = 0; o["roots"]["bookmark_bar"]["children"][i] != o["roots"]["bookmark_bar"]["children"].Last; i++)
{
var property = o["roots"]["bookmark_bar"]["children"][i]["url"];
var property2 = o["roots"]["bookmark_bar"]["children"][i]["children"];
Console.WriteLine(o["roots"]["bookmark_bar"]["children"][i]["type"]);
if (o["roots"]["bookmark_bar"]["children"][i]["type"].ToString() == "url") {
Console.WriteLine("URL");
}
else if (o["roots"]["bookmark_bar"]["children"][i]["type"].ToString() == "folder")
{
Console.WriteLine("FOLDER");
for (int ii = 0; o["roots"]["bookmark_bar"]["children"][i]["children"][ii] != o["roots"]["bookmark_bar"]["children"][i]["children"].Last; ii++)
{
property = o["roots"]["bookmark_bar"]["children"][i]["children"][ii];
// Console.WriteLine(property);
if (o["roots"]["bookmark_bar"]["children"][i]["type"].ToString() == "url")
{
Console.WriteLine("URL");
}
else if (o["roots"]["bookmark_bar"]["children"][i]["type"].ToString() == "folder")
{
for (int iii = 0; o["roots"]["bookmark_bar"]["children"][i]["children"][ii]["children"][iii] != o["roots"]["bookmark_bar"]["children"][i]["children"][ii]["children"].Last; iii++)
{
if (o["roots"]["bookmark_bar"]["children"][i]["type"].ToString() == "url")
{
Console.WriteLine("URL");
}
else if (o["roots"]["bookmark_bar"]["children"][i]["type"].ToString() == "folder")
{
//etc. etc.
}
}
}
}
}
}
So, how can I rewrite this code, without copy/pasting the previous for loops and If-Else statements into where I said 'etc. etc'?
Thanks!
Edit: This is class o:
JsonSerializer serializer = new JsonSerializer();
var o = (JToken)serializer.Deserialize(jsonReader);
This would be a solution for your problem. As I said you process childs recursive.
private void processJsonInput()
{
var reader = new StreamReader(new FileStream("d:\\jsonfile.txt", FileMode.Open));
JsonSerializer serializer = new JsonSerializer();
var o = (JToken)serializer.Deserialize(new JsonTextReader(reader));
foreach (var child in o["roots"]["bookmark_bar"]["children"])
{
processChild(child);
}
}
private void processChild(JToken child)
{
if (child["type"].ToString() == "url")
{
Console.WriteLine("URL");
}
else if (child["type"].ToString() == "folder")
{
Console.WriteLine("FOLDER");
// process sub childrens in the folder
foreach (var subChild in child["children"])
{
processChild(subChild);
}
}
}

Categories