Update all keys with a specific prefix in Newtonsoft JObject - c#

How can I update all keys with a given prefix at all levels in a JObject with a specific value? e.g.
{
"nameOne": "dave",
"age": 23,
"foo": {
"nameTwo": "pete",
"age": 56
}
}
How can I update nameOne and nameTwo (name*) to "chris"?

if it goes no deeper than in your example you can try this
_settings = JObject.Parse(File.ReadAllText(SettingsFile));
_settings["nameOne"]="cris";
_settings["foo"]["nameTwo"]="cris";
or if you need some search, try this
var searchString = "name";
var newValue = "cris";
foreach (var property in _settings)
{
var key = property.Key;
if (property.GetType().Name != "JObject")
{
if (key.Contains(searchString)) _settings[key] = newValue;
}
else
{
JObject prop = _settings[key] as JObject;
foreach (var nestedProperty in prop)
{
var nestedKey = nestedProperty.Key;
if (nestedKey.Contains(searchString)) prop[nestedKey] = newValue;
}
}
}
instead of Contains you can use StartWith or EndsWith as well
it was tested in visual studio
{
"nameOne": "cris",
"age": 23,
"foo": {
"nameTwo": "cris",
"age": 56
}
}

Related

Pick only one record from a JSON array in C#

I'm trying to extract a record from a JSON array but it doesn't seem to work.
Here my code :
DataTable table = ConvertJsonToDatatable(responseBody);
System.Windows.Forms.MessageBox.Show(table.Columns[1].ToString(), "transformation");
The MessageBox isn't showing. I have checked responseBody and the variable isn't empty at all.
Here the structure of this variable (and the JSON array rear)
{
"data":
[
[
1651217520000,
1.0562,
1.0562,
1.056,
1.0561,
0,
0
],
[
1651217580000,
1.0561,
1.0563,
1.0561,
1.0561,
0,
0
]
],
"events": null
}
public static DataTable ConvertJsonToDatatable(string jsonString)
{
var jsonLinq = JObject.Parse(jsonString);
// Find the first array using Linq
var linqArray = jsonLinq.Descendants().Where(x => x is JArray).First();
var jsonArray = new JArray();
foreach (JObject row in linqArray.Children<JObject>())
{
var createRow = new JObject();
foreach (JProperty column in row.Properties())
{
// Only include JValue types
if (column.Value is JValue)
{
createRow.Add(column.Name, column.Value);
}
}
jsonArray.Add(createRow);
}
return JsonConvert.DeserializeObject<DataTable>(jsonArray.ToString());
}
Does anyone have an idea of how to extract/pick one value from this array (which is a string in my code) ?
Have a nice week end everyone and thanks in advance
you have to fix table creating code
public static DataTable ConvertJsonToDatatable(string jsonString)
{
var jsonLinq = JObject.Parse(jsonString);
// Find the first array using Linq
var linqArray = jsonLinq.Descendants().Where(x => x is JArray).First();
//or maybe this would be enough
var linqArray = JObject.Parse(jsonString)["data"];
var jsonArray = new JArray();
foreach (var row in (JArray)linqArray)
{
var createdRow = new JObject();
var i = 0;
foreach (var item in row)
{
i++;
createdRow.Add("col" + i.ToString(), (string)item);
}
jsonArray.Add(createdRow);
}
return jsonArray.ToObject<DataTable>();
}
how to use
DataTable table = ConvertJsonToDatatable(responseBody);
string val = table.Rows[0].Field<string>("col2");
System.Windows.Forms.MessageBox.Show(val, "transformation");
i probably would be marked negative, but i try to explain how it looks like inside. i made example to show tow to get back list of arrays it might visualize for you.
void Main()
{
string json = "{\"data\":[[1651217520000,1.0562,1.0562,1.056,1.0561,0,0],[1651217580000,1.0561,1.0563,1.0561,1.0561,0,0]],\"events\":null}";
var obj = JObject.Parse(json);
foreach (JToken token in obj.FindTokens("data"))
{
foreach (JArray row in JArray.Parse(token.ToString()))
{
row.Dump();
row[0].Dump("first element");
}
}
}
public static class JsonExtensions
{
public static List<JToken> FindTokens(this JToken containerToken, string name)
{
List<JToken> matches = new List<JToken>();
FindTokens(containerToken, name, matches);
return matches;
}
private static void FindTokens(JToken containerToken, string name, List<JToken> matches)
{
if (containerToken.Type == JTokenType.Object)
{
foreach (JProperty child in containerToken.Children<JProperty>())
{
if (child.Name == name)
{
matches.Add(child.Value);
}
FindTokens(child.Value, name, matches);
}
}
else if (containerToken.Type == JTokenType.Array)
{
foreach (JToken child in containerToken.Children())
{
FindTokens(child, name, matches);
}
}
}
}
result would be an array of jarray
so you can build you DataTable rows
.Dump() is a left over from linqpad. Good tool. Same as console.write

Deep count for object properties

I'd like to count the number of properties within an object.
I have found several solutions but none really counts the child\nested propertie.
For instance, I have the following JSON object.
{
"id": "259a36d2-3852-425f-a70c-3f9477753210",
"name": "foo",
"type": "na",
"text": "ABC.pdf",
"left": 333,
"top": 130,
"w": 134,
"h": 34,
"customData": {
"A": "fa6css4ec8-8ffb-55bca4dde06a",
"name": "SDF.pdf",
"IsExists": false,
"PNumber": 1,
}
}
When trying the following I'm getting the result of 9, while I'm expecting 12 (which is the count of the entire properties).
JObject sourceJObject = JsonConvert.DeserializeObject<JObject>(json);
var res= sourceJObject.Count;
I'll be happy for assistant.
JObject.Count is documented as returning the count of child tokens - not all descendant tokens. So while you may want 12, you shouldn't really expect 12.
If you want the count of all descendants, you can use sourceJObject.Descendants().Count(). However, that will give you 13 rather than 12, because customData itself is a token.
If you want "all descendant properties where the value isn't an object" you can use OfType and Where, as shown in the code below. You should probably think about what you want to do with arrays though...
using Newtonsoft.Json.Linq;
string json = File.ReadAllText("test.json");
JObject jobject = JObject.Parse(json);
var properties = jobject.Descendants()
.OfType<JProperty>()
.Where(prop => prop.Value is not JObject);
Console.WriteLine($"Count: {properties.Count()}");
foreach (var property in properties)
{
Console.WriteLine($"{property.Name} = {property.Value}");
}
Output:
Count: 12
id = 259a36d2-3852-425f-a70c-3f9477753210
name = foo
type = na
text = ABC.pdf
left = 333
top = 130
w = 134
h = 34
A = fa6css4ec8-8ffb-55bca4dde06a
name = SDF.pdf
IsExists = False
PNumber = 1
try this
var obj=JObject.Parse(json);
var count=0;
CountProps(obj, ref count); // count=12
public void CountProps(JToken obj, ref int count)
{
if (obj is JObject)
foreach (var property in ((JObject)obj).Properties())
{
if (property.Value is JValue) count++;
if (property.Value is JObject) CountProps(property.Value, ref count);
if (property.Value is JArray) { count++; CountProps(property.Value, ref count); }
}
if (obj.GetType().Name == "JArray")
foreach (var property in ((JArray)obj))
if (property is JObject || property is JArray) CountProps(property, ref count);
}

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.

Categories