1
0
Files
common/AMWD.Common/Extensions/JsonExtensions.cs

183 lines
6.7 KiB
C#

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>
/// 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>
/// <returns>A new instance of <typeparamref name="T"/> with the deserialized values.</returns>
public static T DeserializeJson<T>(this string json)
=> JsonConvert.DeserializeObject<T>(json, _jsonSerializerSettings);
/// <summary>
/// Deserializes a JSON string into a new instance or using the fallback value.
/// </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="fallbackValue">A fallback value when deserialization fails.</param>
/// <returns>A new instance of <typeparamref name="T"/> with the deserialized values or the fallback value.</returns>
public static T DeserializeJson<T>(this string json, T fallbackValue)
{
try
{
return JsonConvert.DeserializeObject<T>(json, _jsonSerializerSettings);
}
catch
{
return fallbackValue;
}
}
/// <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;
};
serializer.TypeNameHandling = includeType ? TypeNameHandling.All : TypeNameHandling.None;
serializer.Serialize(jw, source, typeof(T));
}
return sb.ToString().Trim();
}
/// <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;
string lvl = level;
if (lvlObj.Type == JTokenType.Object)
{
foreach (var prop in ((JObject)lvlObj).Properties())
{
if (prop.Name.Equals(lvl, System.StringComparison.OrdinalIgnoreCase))
{
lvl = prop.Name;
break;
}
}
}
lvlObj = lvlObj[lvl];
}
if (lvlObj == null)
return defaultValue;
return DeepConvert.ChangeType<T>(lvlObj is JValue lvlValue ? lvlValue.Value : lvlObj.Value<object>());
}
/// <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);
}
}