public static bool TryToRestoreDamagedJsonFile(string filename, JObjectRestorationScheme scheme) { var data = File.ReadAllText(filename); var jObject = JsonExtension.TryToRestore(data, scheme); if (jObject == null) return false; FileUtils.Recycle(filename); File.WriteAllText(filename, jObject.ToString()); return true; }
public static JObject TryToRestore([LocalizationRequired(false)] string damagedJson, JObjectRestorationScheme scheme) { var result = new JObject(); var input = Regex.Replace(damagedJson, @"\r?\n|\n", "\n").Trim(); foreach (var field in scheme.Fields) { var match = Regex.Match(input, $@"(?:""\s*{field.Name}\s*""|'\s*{field.Name}\s*'|{field.Name})\s*:\s*([\s\S]+)"); if (!match.Success) { continue; } var value = match.Groups[1].Value.Trim(); if (!field.IsMultiline) { value = value.Split('\n')[0]; value = Regex.Replace(value, @"\s*,?\s*(""\s*\w+\s*""|'\s*\w+\s*'|\w+)\s*:[\s\S]+|\s*}", ""); } value = Regex.Replace(value, @"(?:\n?\s*,?\s*(""\s*\w+\s*""|'\s*\w+\s*'|\w+)\s*:|\s*})[\s\S]*$", ""); value = Regex.Replace(value.Trim(), @",$", ""); JToken processedValue; if (value == "null") { processedValue = null; } else { switch (field.Type) { case JObjectRestorationScheme.FieldType.String: case JObjectRestorationScheme.FieldType.NonNullString: case JObjectRestorationScheme.FieldType.StringMultiline: processedValue = DequoteString(value); break; case JObjectRestorationScheme.FieldType.Number: var doubleValue = FlexibleParser.ParseDouble(value); if (Equals(doubleValue % 1.0, 0.0)) { processedValue = (long)doubleValue; } else { processedValue = doubleValue; } break; case JObjectRestorationScheme.FieldType.Boolean: processedValue = Regex.IsMatch(value, @"\b(true|on|yes|1)\b", RegexOptions.IgnoreCase); break; case JObjectRestorationScheme.FieldType.StringsArray: processedValue = new JArray( Regex.Split(value, @"^\s*\[|(?<!\\)""\s*,?\s*""|\s*(?:,\s*\n|\n\s*,?)\s*|\]\s*$") .Select(DequoteString) .Where(x => x.Length > 0 && x != "[" && x != "]") .Cast <object>().ToArray()); break; case JObjectRestorationScheme.FieldType.PairsArray: processedValue = new JArray( Regex.Split(value, @"^\s*\[|(?<!\\)""\s*\]?\s*,\s*\[??\s*""|\s*\]?\s*(?:,\s*\n|\n\s*,?)\s*\[?\s*|\]\s*$") .Select(DequoteString) .Where(x => x.Length > 0 && x != "[" && x != "]") .Partition(2) .Where(x => x.Length == 2) .Select(x => new JArray(x.ToArray <object>())) .Cast <object>().ToArray()); break; default: throw new ArgumentOutOfRangeException(); } } if (field.ParentName != null) { if (!(result[field.ParentName] is JObject obj)) { result[field.ParentName] = obj = new JObject(); } obj[field.Name] = processedValue; } else { result[field.Name] = processedValue; } } foreach (var field in scheme.Fields.Where(x => x.Type == JObjectRestorationScheme.FieldType.NonNullString && !result.TryGetValue(x.Name, out _))) { if (field.ParentName != null) { if (!(result[field.ParentName] is JObject obj)) { result[field.ParentName] = obj = new JObject(); } obj[field.Name] = ""; } else { result[field.Name] = ""; } } return(result); }
public static JObject TryToRestore([LocalizationRequired(false)] string damagedJson, JObjectRestorationScheme scheme) { var result = new JObject(); var input = Regex.Replace(damagedJson, @"\r?\n|\n", "\n").Trim(); foreach (var field in scheme.Fields) { var match = Regex.Match(input, $@"(?:""\s*{field.Name}\s*""|'\s*{field.Name}\s*'|{field.Name})\s*:\s*([\s\S]+)"); if (!match.Success) continue; var value = match.Groups[1].Value.Trim(); if (!field.IsMultiline) { value = value.Split('\n')[0]; value = Regex.Replace(value, @"\s*,?\s*(""\s*\w+\s*""|'\s*\w+\s*'|\w+)\s*:[\s\S]+|\s*}", ""); } value = Regex.Replace(value, @"(?:\n?\s*,?\s*(""\s*\w+\s*""|'\s*\w+\s*'|\w+)\s*:|\s*})[\s\S]*$", ""); value = Regex.Replace(value.Trim(), @",$", ""); JToken processedValue; if (value == "null") { processedValue = null; } else { switch (field.Type) { case JObjectRestorationScheme.FieldType.String: case JObjectRestorationScheme.FieldType.NonNullString: case JObjectRestorationScheme.FieldType.StringMultiline: processedValue = DequoteString(value); break; case JObjectRestorationScheme.FieldType.Number: var doubleValue = FlexibleParser.ParseDouble(value); if (Equals(doubleValue % 1.0, 0.0)) { processedValue = (long)doubleValue; } else { processedValue = doubleValue; } break; case JObjectRestorationScheme.FieldType.Boolean: processedValue = Regex.IsMatch(value, @"\b(true|on|yes|1)\b", RegexOptions.IgnoreCase); break; case JObjectRestorationScheme.FieldType.StringsArray: processedValue = new JArray( Regex.Split(value, @"^\s*\[|(?<!\\)""\s*,?\s*""|\s*(?:,\s*\n|\n\s*,?)\s*|\]\s*$") .Select(DequoteString) .Where(x => x.Length > 0 && x != "[" && x != "]") .Cast<object>().ToArray()); break; case JObjectRestorationScheme.FieldType.PairsArray: processedValue = new JArray( Regex.Split(value, @"^\s*\[|(?<!\\)""\s*\]?\s*,\s*\[??\s*""|\s*\]?\s*(?:,\s*\n|\n\s*,?)\s*\[?\s*|\]\s*$") .Select(DequoteString) .Where(x => x.Length > 0 && x != "[" && x != "]") .Partition(2) .Where(x => x.Length == 2) .Select(x => new JArray(x.Cast<object>().ToArray())) .Cast<object>().ToArray()); break; default: throw new ArgumentOutOfRangeException(); } } if (field.ParentName != null) { var obj = result[field.ParentName] as JObject; if (obj == null) { result[field.ParentName] = obj = new JObject(); } obj[field.Name] = processedValue; } else { result[field.Name] = processedValue; } } JToken temp; foreach (var field in scheme.Fields.Where(x => x.Type == JObjectRestorationScheme.FieldType.NonNullString && !result.TryGetValue(x.Name, out temp))) { if (field.ParentName != null) { var obj = result[field.ParentName] as JObject; if (obj == null) { result[field.ParentName] = obj = new JObject(); } obj[field.Name] = ""; } else { result[field.Name] = ""; } } return result; }