162 lines
5.9 KiB
C#
162 lines
5.9 KiB
C#
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
|
|
{
|
|
/// <summary>
|
|
/// Provides extension methods to serialize and deserialize JSON values to/from objects using
|
|
/// common naming conventions.
|
|
/// </summary>
|
|
public static class JsonExtensions
|
|
{
|
|
/// <summary>
|
|
/// Common JSON serializer settings.
|
|
/// </summary>
|
|
private static readonly JsonSerializerSettings jsonSerializerSettings = new()
|
|
{
|
|
ContractResolver = new CamelCasePropertyNamesContractResolver(),
|
|
Culture = CultureInfo.InvariantCulture
|
|
};
|
|
|
|
/// <summary>
|
|
/// Populates an instance with values deserialized from a JSON string.
|
|
/// </summary>
|
|
/// <typeparam name="T">The type of the instance to populate.</typeparam>
|
|
/// <param name="target">The instance to populate.</param>
|
|
/// <param name="json">The JSON string to read the values from.</param>
|
|
public static void DeserializeJson<T>(this T target, string json)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(json))
|
|
JsonConvert.PopulateObject(json, target, jsonSerializerSettings);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Serializes an instance to a JSON string.
|
|
/// </summary>
|
|
/// <typeparam name="T">The type of the instance to serialize.</typeparam>
|
|
/// <param name="source">The instance to serialize.</param>
|
|
/// <param name="indented">Indicates whether the JSON string is indented to make it better readable.</param>
|
|
/// <param name="useSingleQuotes">Indicates whether the JSON string uses single quotes instead of double quotes.</param>
|
|
/// <param name="useCamelCase">Indicates whether the camelCase conversion should be used.</param>
|
|
/// <param name="includeType">Indicates whether to include the instance type of <paramref name="source"/> if it is not <typeparamref name="T"/>.</param>
|
|
/// <returns>The JSON-serialized string.</returns>
|
|
public static string SerializeJson<T>(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();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Deserializes a JSON string into a new instance.
|
|
/// </summary>
|
|
/// <typeparam name="T">The type of the instance to deserialize.</typeparam>
|
|
/// <param name="json">The JSON string to read the values from.</param>
|
|
/// <param name="fallback">A fallback value.</param>
|
|
/// <returns>A new instance of <typeparamref name="T"/> with the deserialized values.</returns>
|
|
public static T DeserializeJson<T>(this string json, T fallback = default)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(json))
|
|
return JsonConvert.DeserializeObject<T>(json, jsonSerializerSettings);
|
|
|
|
return fallback;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts an object into a JObject using the custom serializer settings.
|
|
/// </summary>
|
|
/// <param name="obj">The object to convert.</param>
|
|
/// <returns>A JObject representing the <paramref name="obj"/>.</returns>
|
|
public static JObject ConvertToJObject(this object obj)
|
|
{
|
|
if (obj == null)
|
|
return null;
|
|
|
|
var serializer = JsonSerializer.Create(jsonSerializerSettings);
|
|
return JObject.FromObject(obj, serializer);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts an enumerable into a JArray using the custom serializer settings.
|
|
/// </summary>
|
|
/// <param name="array">The enumerable to convert.</param>
|
|
/// <returns>A JArray representing the <paramref name="array"/>.</returns>
|
|
public static JArray ConvertToJArray(this IEnumerable array)
|
|
{
|
|
if (array == null)
|
|
return null;
|
|
|
|
var serializer = JsonSerializer.Create(jsonSerializerSettings);
|
|
return JArray.FromObject(array, serializer);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a value from the object using multiple levels.
|
|
/// </summary>
|
|
/// <typeparam name="T">The type to convert the data to.</typeparam>
|
|
/// <param name="jObj">The object.</param>
|
|
/// <param name="key">The key to the value.</param>
|
|
/// <param name="defaultValue">The default value when the key was not found.</param>
|
|
/// <param name="keySplit">The character to split the key in levels (default: colon).</param>
|
|
/// <returns>The converted value.</returns>
|
|
public static T GetValue<T>(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<T>(lvlObj);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a value from the object using multiple levels.
|
|
/// </summary>
|
|
/// <typeparam name="T">The type to convert the data to.</typeparam>
|
|
/// <param name="jObj">The object.</param>
|
|
/// <param name="key">The key to the value.</param>
|
|
/// <param name="keySplit">The character to split the key in levels (default: colon).</param>
|
|
/// <returns>The converted value.</returns>
|
|
public static T GetValue<T>(this JObject jObj, string key, char keySplit = ':')
|
|
=> jObj.GetValue(key, default(T), keySplit);
|
|
}
|
|
}
|