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);
}
}