Skip to content

Instantly share code, notes, and snippets.

@mishrsud
Created May 28, 2021 12:48
Show Gist options
  • Save mishrsud/4f9a2f18f305a6367bff2d83aac11b5a to your computer and use it in GitHub Desktop.
Save mishrsud/4f9a2f18f305a6367bff2d83aac11b5a to your computer and use it in GitHub Desktop.
Snake Case Serilization with System.Text.Json
using System;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Infrastructure
{
public static class JsonSerializationExtensions
{
public static readonly JsonSerializerOptions SnakeCaseSerializerOptions = new()
{
WriteIndented = false,
PropertyNamingPolicy = new SnakeCaseNamingPolicy(),
PropertyNameCaseInsensitive = true,
IgnoreNullValues = true,
Converters = { new JsonStringEnumConverter(allowIntegerValues: false) }
};
/// <summary>
/// Converts the object instance passed in to JSON using <see cref="System.Text.Json.JsonSerializer"/>
/// </summary>
/// <param name="objectToSerialize">The object instance to serialize</param>
/// <param name="serializerOptions">A <see cref="JsonSerializerOptions"/> instance. Defaults to snake_case</param>
/// <typeparam name="T"></typeparam>
public static string ToJson<T>(this T objectToSerialize, JsonSerializerOptions? serializerOptions = null)
{
return JsonSerializer.Serialize(objectToSerialize, serializerOptions ?? SnakeCaseSerializerOptions);
}
/// <summary>
/// Converts the string passed in to an instance of T using <see cref="System.Text.Json.JsonSerializer"/>
/// </summary>
/// <param name="json">The string to convert</param>
/// <param name="serializerOptions">A <see cref="JsonSerializerOptions"/> instance. Defaults to snake_case</param>
/// <typeparam name="T"></typeparam>
public static T FromJson<T>(this string json, JsonSerializerOptions? serializerOptions = null)
{
return JsonSerializer.Deserialize<T>(json, serializerOptions ?? SnakeCaseSerializerOptions)!;
}
// Copied from https://github.com/michaelrosedev/snakecase_json/blob/dbc70b7e137e42716350685f684bd46d0458d056/Sample.Serialization/StringExtensions.cs#L12
public static string ToSnakeCaseAsSpan(this string str)
{
const char Separator = '_';
if (str == null)
{
return string.Empty;
}
var strSpan = str.AsSpan();
var bufferSize = str.Length + str.Count(t => t >= 'A' && t <= 'Z' && t != str[0]);
Span<char> buffer = new char[bufferSize];
var bufferPosition = 0;
var namePosition = 0;
while (bufferPosition < buffer.Length)
{
if (namePosition > 0 && strSpan[namePosition] >= 'A' && strSpan[namePosition] <= 'Z')
{
buffer[bufferPosition] = Separator;
buffer[bufferPosition + 1] = strSpan[namePosition];
bufferPosition += 2;
namePosition++;
continue;
}
buffer[bufferPosition] = strSpan[namePosition];
bufferPosition++;
namePosition++;
}
return new string(buffer).ToLower();
}
}
public class SnakeCaseNamingPolicy : JsonNamingPolicy
{
public override string ConvertName(string name)
{
return name.ToSnakeCaseAsSpan();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment