I'm trying to convert a nested json to simple json by recursively traversing. (Structure of input json is unknown)
for example, I want json like this
{
"FirstName": "Rahul",
"LastName": "B",
"EmpType": {
"RID": 2,
"Title": "Full Time"
},
"CTC": "3.5",
"Exp": "1",
"ComplexObj": {
"RID": 3,
"Title": {
"Test": "RID",
"TWO": {
"Test": 12
}
}
}
}
to be converted something like this
{
"FirstName": "Rahul",
"LastName": "B",
"EmpType__RID": 2,
"EmpType__Title": "Full Time",
"CTC": "3.5",
"Exp": "1",
"ComplexObj__RID": 3,
"ComplexObj__Title__Test": "RID",
"ComplexObj__Title__TWO__Test": 12
}
each fields in nested object will be changed to key which represents its actual path.
this is what I have done so far.
public static void ConvertNestedJsonToSimpleJson(JObject jobject, ref JObject jobjectRef, string currentNodeName = "", string rootPath = "")
{
string propName = "";
if (currentNodeName.Equals(rootPath))
{
propName = currentNodeName;
}
else
{
propName = (rootPath == "" && currentNodeName == "") ? rootPath + "" + currentNodeName : rootPath + "__" + currentNodeName;
}
foreach (JProperty jprop in jobject.Properties())
{
if (jprop.Children<JObject>().Count() == 0)
{
jobjectRef.Add(propName == "" ? jprop.Name : propName + "__" + jprop.Name, jprop.Value);
}
else
{
currentNodeName = jprop.Name;
rootPath = rootPath == "" ? jprop.Name : rootPath;
ConvertNestedJsonToSimpleJson(JObject.Parse(jprop.Value.ToString()), ref jobjectRef, currentNodeName, rootPath);
}
}
}
and getting wrong result
{
"FirstName": "Rahul",
"LastName": "B",
"EmpType__RID": 2,
"EmpType__Title": "Full Time",
"CTC": "3.5",
"Exp": "1",
"EmpType__ComplexObj__RID": 3,
"EmpType__Title__Test": "RID",
"EmpType__two__Test": 12
}
will appreciate any help on correcting my code, or any other approach to archive this.
Nested JSON is simply a JSON file with a fairly big portion of its values being other JSON objects. Compared with Simple JSON, Nested JSON provides higher clarity in that it decouples objects into different layers, making it easier to maintain. Using Phrase, keys will be stored by separating levels with a dot.
Objects can be nested inside other objects. Each nested object must have a unique access path. The same field name can occur in nested objects in the same document.
A JsonNode is Jackson's tree model for JSON and it can read JSON into a JsonNode instance and write a JsonNode out to JSON. To read JSON into a JsonNode with Jackson by creating ObjectMapper instance and call the readValue() method. We can access a field, array or nested object using the get() method of JsonNode class.
JObject
prefix + jprop.Name + "__"
The code:
public static void FlattenJson(JObject node, JObject result, string prefix = "")
{
foreach (var jprop in node.Properties())
{
if (jprop.Children<JObject>().Count() == 0)
{
result.Add(prefix + jprop.Name, jprop.Value);
}
else
{
FlattenJson((JObject)jprop.Value, $"{prefix}{jprop.Name}__", result);
}
}
}
You can call it like this:
var node = JObject.Parse(/* the input string */);
var result = new JObject();
FlattenJson(node, result);
Your problem is in the line rootPath = rootPath == "" ? jprop.Name : rootPath;
. You are changing the rootPath when you first come across EmpType
which means when you process ComplexObj
your rootPath is wrong. What I believe you intended is just to change what you were passing into the recursive function.
As it is though it is unnecessary to keep track of root and currentnode as two separate items. Better would be to just track the current prefix for a given node in code that looks more like this:
public static void ConvertNestedJsonToSimpleJson(JObject input, JObject output, string prefix = "")
{
foreach (JProperty jprop in input.Properties())
{
var name = prefix==""?jprop.Name:String.Format("{0}__{1}", prefix,jprop.Name);
if (jprop.Children<JObject>().Count() == 0)
{
output.Add(name, jprop.Value);
}
else
{
ConvertNestedJsonToSimpleJson((JObject)jprop.Value, output, name);
}
}
}
This now gives me the output:
{
"FirstName": "Rahul",
"LastName": "B",
"EmpType__RID": 2,
"EmpType__Title": "Full Time",
"CTC": "3.5",
"Exp": "1",
"ComplexObj__RID": 3,
"ComplexObj__Title__Test": "RID",
"ComplexObj__Title__TWO__Test": 12
}
which looks correct.
Could you do something like this using linq
var jsonObj = jobject.select(x => new CustomJson {
FirstName = x.FirstName,
LastName = x.LastName,
EmpTypeId = x.EmpType.Id,
Title = x.EmpType.Title
etc etc
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With