using System; using System.Collections; using System.Globalization; using System.IO; using System.Text; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; using Unclassified.Util; namespace Newtonsoft.Json { /// /// Provides extension methods to serialize and deserialize JSON values to/from objects using /// common naming conventions. /// public static class JsonExtensions { /// /// Common JSON serializer settings. /// private static readonly JsonSerializerSettings jsonSerializerSettings = new() { ContractResolver = new CamelCasePropertyNamesContractResolver(), Culture = CultureInfo.InvariantCulture }; /// /// Populates an instance with values deserialized from a JSON string. /// /// The type of the instance to populate. /// The instance to populate. /// The JSON string to read the values from. public static void DeserializeJson(this T target, string json) { if (!string.IsNullOrWhiteSpace(json)) JsonConvert.PopulateObject(json, target, jsonSerializerSettings); } /// /// Serializes an instance to a JSON string. /// /// The type of the instance to serialize. /// The instance to serialize. /// Indicates whether the JSON string is indented to make it better readable. /// Indicates whether the JSON string uses single quotes instead of double quotes. /// Indicates whether the camelCase conversion should be used. /// Indicates whether to include the instance type of if it is not . /// The JSON-serialized string. public static string SerializeJson(this T source, bool indented = false, bool useSingleQuotes = false, bool useCamelCase = true, bool includeType = false) { var sb = new StringBuilder(); using (var sw = new StringWriter(sb)) using (var jw = new JsonTextWriter(sw)) { if (useSingleQuotes) jw.QuoteChar = '\''; jw.Formatting = indented ? Formatting.Indented : Formatting.None; var serializer = useCamelCase ? JsonSerializer.Create(jsonSerializerSettings) : JsonSerializer.CreateDefault(); serializer.Error += (s, a) => { a.ErrorContext.Handled = true; }; if (includeType) serializer.TypeNameHandling = TypeNameHandling.Auto; serializer.Serialize(jw, source, typeof(T)); } return sb.ToString().Trim(); } /// /// Deserializes a JSON string into a new instance. /// /// The type of the instance to deserialize. /// The JSON string to read the values from. /// A fallback value. /// A new instance of with the deserialized values. public static T DeserializeJson(this string json, T fallback = default) { if (!string.IsNullOrWhiteSpace(json)) return JsonConvert.DeserializeObject(json, jsonSerializerSettings); return fallback; } /// /// Converts an object into a JObject using the custom serializer settings. /// /// The object to convert. /// A JObject representing the . public static JObject ConvertToJObject(this object obj) { if (obj == null) return null; var serializer = JsonSerializer.Create(jsonSerializerSettings); return JObject.FromObject(obj, serializer); } /// /// Converts an enumerable into a JArray using the custom serializer settings. /// /// The enumerable to convert. /// A JArray representing the . public static JArray ConvertToJArray(this IEnumerable array) { if (array == null) return null; var serializer = JsonSerializer.Create(jsonSerializerSettings); return JArray.FromObject(array, serializer); } /// /// Gets a value from the object using multiple levels. /// /// The type to convert the data to. /// The object. /// The key to the value. /// The default value when the key was not found. /// The character to split the key in levels (default: colon). /// The converted value. public static T GetValue(this JObject jObj, string key, T defaultValue, char keySplit = ':') { if (jObj == null) return defaultValue; string[] levels = key.Split(keySplit); JToken lvlObj = jObj; foreach (string level in levels) { if (lvlObj == null) return defaultValue; lvlObj = lvlObj[level]; } if (lvlObj == null) return defaultValue; if (typeof(T) == typeof(string)) return (T)Convert.ChangeType(lvlObj, typeof(T)); return DeepConvert.ChangeType(lvlObj); } /// /// Gets a value from the object using multiple levels. /// /// The type to convert the data to. /// The object. /// The key to the value. /// The character to split the key in levels (default: colon). /// The converted value. public static T GetValue(this JObject jObj, string key, char keySplit = ':') => jObj.GetValue(key, default(T), keySplit); } }