using Newtonsoft.Json.Linq;
using System.Collections.Generic;
private const string INPUT_FILE = "path of the input json";
private static void Main(string[] args)
var input = File.ReadAllText(INPUT_FILE);
var output = ConvertFlatJson(input);
Console.WriteLine(output);
public static string ConvertFlatJson(string input)
var token = JToken.Parse(input);
if (token is JObject obj)
return ConvertJObject(obj).ToString();
if (token is JArray array)
return ConvertArray(array).ToString();
private static JObject ConvertJObject(JObject input)
var enumerable = ((IEnumerable<KeyValuePair<string, JToken>>)input).OrderBy(kvp => kvp.Key);
var result = new JObject();
foreach (var outerField in enumerable)
var key = outerField.Key;
var value = outerField.Value;
if (value is JArray array)
value = ConvertArray(array);
var fieldNames = key.Split('.');
for (var fieldNameIndex = 0; fieldNameIndex < fieldNames.Length; fieldNameIndex++)
var fieldName = fieldNames[fieldNameIndex];
if (fieldNameIndex == fieldNames.Length - 1)
currentObj[fieldName] = value;
if (currentObj.ContainsKey(fieldName))
currentObj = (JObject)currentObj[fieldName];
var newObj = new JObject();
currentObj[fieldName] = newObj;
private static JArray ConvertArray(JArray array)
var resultArray = new JArray();
foreach (var arrayItem in array)
if (!(arrayItem is JObject))
resultArray.Add(arrayItem);
var itemObj = (JObject)arrayItem;
resultArray.Add(ConvertJObject(itemObj));
private static void ParseJson()
var input = File.ReadAllText("sample.txt");
Console.WriteLine(input);
Console.WriteLine("\n\n");
Console.WriteLine(Convert(input));
private static string Convert(string input)
var result = new Dictionary<string, object>();
.Substring(1, input.Length - 2)
var pair = i.Split(new[] { ':' }, 2);
return new KeyValuePair<string, string>(pair[0], pair[1]);
var nonObjectItems = keyValues.Where(kvp => !kvp.Key.Contains('.'));
foreach (var item in nonObjectItems)
result[item.Key.Unquote()] = item.Value.Unquote();
var objectItems = keyValues.Except(nonObjectItems).ToDictionary(kvp => kvp.Key.Unquote(), kvp => kvp.Value.Unquote());
ConvertNestedObjects(objectItems, ref result);
return JsonConvert.SerializeObject(result, Formatting.Indented);
private static void ConvertNestedObjects(IDictionary<string, string> items, ref Dictionary<string, object> result)
var objectNames = items.Keys.Select(k => k.Substring(0, k.IndexOf('.'))).Distinct();
foreach (var objName in objectNames)
var dict = items.Where(kvp => kvp.Key.StartsWith(objName + ".")).ToDictionary(kvp => kvp.Key.Substring(objName.Length + 1), kvp => kvp.Value);
var directItems = dict.Where(kvp => !kvp.Key.Contains('.'));
var obj = directItems.ToDict();
var nestedObjItems = dict.Except(directItems).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
if (nestedObjItems.Count > 0)
ConvertNestedObjects(nestedObjItems, ref obj);
private static readonly char[] TrimChars = new[] { '"' };
public static Dictionary<TKey, object> ToDict<TKey, TValue>(this IEnumerable<KeyValuePair<TKey, TValue>> items)
return items.ToDictionary(kvp => kvp.Key, kvp => (object)kvp.Value);
public static string Unquote(this string input)
return input == "null" ? null : input.Trim(TrimChars);