I have below Json, I need to transform this dotted flat hierarchy into tree view hierarchy
{
"info.clinical.user.gender.1": "female",
"info.clinical.user.gender.2": "male",
"info.clinical.user.age.max": "60",
"info.clinical.user.age.min": "18",
}
How to convert above Json to below JSON in a best and optimized way using C#
{
"info": {
"clinical": {
"user": {
"age": {
"min": 18,
"max": 60
},
"gender": [
"female",
"male"
]
}
}
}
}
CodePudding user response:
try this
var origJsonObj = JObject.Parse(json);
var arrFirst = origJsonObj.Properties().First().Name.Split('.');
var jsonObj = new JObject();
var prevObj = jsonObj;
for (int i = 0; i < arrFirst.Length - 2; i )
{
var currObj = new JObject();
var newProperty = new JProperty(arrFirst[i], currObj);
prevObj.Add(newProperty);
prevObj = currObj;
}
foreach (var prop in origJsonObj.Properties())
{
var arr = prop.Name.Split('.');
var name = arr[arr.Length - 2];
if (int.TryParse(arr[arr.Length - 1], out var index))
{
JArray jArr;
if (prevObj[name] == null)
{
jArr = new JArray();
var newProperty = new JProperty(arr[arr.Length - 2], jArr);
prevObj.Add(newProperty);
}
else jArr = (JArray)prevObj[name];
jArr.Add(prop.Value);
continue;
}
JObject jObj = null;
if (prevObj[name] == null)
{
jObj = new JObject();
prevObj.Add(new JProperty(name, jObj));
}
else jObj = (JObject)prevObj[name];
jObj[arr[arr.Length - 1]] = prop.Value;
}
CodePudding user response:
Maybe you should implement it yourself, like:
using System.Text.Json.Nodes;
namespace FlatJson
{
public static class FlatJson
{
public static JsonObject ToTree(this JsonObject flat, char sep = '.')
{
var result = new JsonObject();
foreach (var flatItem in flat)
{
var layerNames = flatItem.Key.Split(sep);
var lastIndex = layerNames.Length - 1;
var currentLayer = result;
for (int layerIndex = 0; layerIndex < lastIndex; layerIndex )
{
var layerName = layerNames[layerIndex];
var nextLayer = currentLayer[layerName]?.AsObject();
if (nextLayer is not null)
currentLayer = nextLayer;
else
{
nextLayer = new JsonObject();
currentLayer[layerName] = nextLayer;
currentLayer = nextLayer;
}
}
var propertyName = layerNames[lastIndex];
var value = flatItem.Value?.GetValue<object?>();
currentLayer[propertyName] = JsonValue.Create(value);
}
return result;
}
}
}
And how to use it:
using System.Diagnostics;
using System.Text.Json.Nodes;
using FlatJson;
var t = File.ReadAllText("test.json");
JsonObject? obj = JsonNode.Parse(t)?.AsObject();
Debug.Assert(obj is not null);
JsonObject result = obj.ToTree();
Console.WriteLine(obj);
Console.WriteLine();
Console.WriteLine(result);
But as I asked in the comments, we don't really know whether the "60"
here is a number or not, and whether the info.clinical.user.gender
is a list or an object. So the output of my code is (which makes sense to me):
(The original json has been changed to show you how it works in some other situations.)
{
"info.clinical.user.gender.1": "60",
"info.clinical.user.gender.2": "male",
"info.clinical.user.age.max": 60,
"info.clinical.user.age.min": null
}
{
"info": {
"clinical": {
"user": {
"gender": {
"1": "60",
"2": "male"
},
"age": {
"max": 60,
"min": null
}
}
}
}
}