Skip to content

Commit

Permalink
add support for optional naming methods
Browse files Browse the repository at this point in the history
  • Loading branch information
gregsdennis committed Oct 28, 2023
1 parent 7752443 commit ea75cf6
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 6 deletions.
17 changes: 15 additions & 2 deletions JsonPointer/JsonPointer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;
Expand Down Expand Up @@ -155,13 +156,25 @@ public static JsonPointer Create(IEnumerable<PointerSegment> segments)
/// </summary>
/// <typeparam name="T">The type of the object.</typeparam>
/// <param name="expression">The lambda expression which gives the pointer path.</param>
/// <param name="options">(optional) Options for creating the pointer.</param>
/// <returns>The JSON Pointer.</returns>
/// <exception cref="NotSupportedException">
/// Thrown when the lambda expression contains a node that is not a property access or
/// <see cref="int"/>-valued indexer.
/// </exception>
public static JsonPointer Create<T>(Expression<Func<T, object>> expression)
public static JsonPointer Create<T>(Expression<Func<T, object>> expression, PointerCreationOptions? options = null)
{
PointerSegment GetSegment(MemberInfo member)
{
var attribute = member.GetCustomAttribute<JsonPropertyNameAttribute>();
if (attribute is not null)
return attribute.Name;

return options!.PropertyNameResolver!(member);
}

options ??= PointerCreationOptions.Default;

var body = expression.Body;
var segments = new List<PointerSegment>();
while (body != null)
Expand All @@ -171,7 +184,7 @@ public static JsonPointer Create<T>(Expression<Func<T, object>> expression)

if (body is MemberExpression me)
{
segments.Insert(0, PointerSegment.Create(me.Member.Name));
segments.Insert(0, GetSegment(me.Member));
body = me.Expression;
}
else if (body is MethodCallExpression mce1 &&
Expand Down
7 changes: 3 additions & 4 deletions JsonPointer/JsonPointer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Humanizer.Core" Version="2.11.10" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
</ItemGroup>

Expand All @@ -54,10 +55,8 @@
</ItemGroup>

<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Copy SourceFiles="$(TargetDir)$(DocumentationFile)" DestinationFolder="..\json-everything.net\wwwroot\xml\"
SkipUnchangedFiles="True" OverwriteReadOnlyFiles="True" />
<Copy SourceFiles="$(TargetDir)$(DocumentationFile)" DestinationFolder="..\doc-tool\xml\"
SkipUnchangedFiles="True" OverwriteReadOnlyFiles="True" />
<Copy SourceFiles="$(TargetDir)$(DocumentationFile)" DestinationFolder="..\json-everything.net\wwwroot\xml\" SkipUnchangedFiles="True" OverwriteReadOnlyFiles="True" />
<Copy SourceFiles="$(TargetDir)$(DocumentationFile)" DestinationFolder="..\doc-tool\xml\" SkipUnchangedFiles="True" OverwriteReadOnlyFiles="True" />
</Target>

</Project>
14 changes: 14 additions & 0 deletions JsonPointer/PointerCreationOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace Json.Pointer;

public class PointerCreationOptions
{
private PropertyNameResolver? _propertyNameResolver;

public static PointerCreationOptions Default = new();

public PropertyNameResolver? PropertyNameResolver
{
get => _propertyNameResolver ??= PropertyNameResolvers.AsDeclared;
set => _propertyNameResolver = value;
}
}
46 changes: 46 additions & 0 deletions JsonPointer/PropertyNameResolvers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System.Reflection;
using Humanizer;

namespace Json.Pointer;

/// <summary>
/// Declares a property name resolution which is used to provide a property name.
/// </summary>
/// <param name="input">The property.</param>
/// <returns>The property name</returns>
public delegate string PropertyNameResolver(MemberInfo input);

/// <summary>
/// Defines a set of predefined property name resolution methods.
/// </summary>
public static class PropertyNameResolvers
{
/// <summary>
/// Makes no changes. Properties are generated with the name of the property in code.
/// </summary>
public static readonly PropertyNameResolver AsDeclared = x => x.Name;
/// <summary>
/// Property names to camel case (e.g. `camelCase`).
/// </summary>
public static readonly PropertyNameResolver CamelCase = x => x.Name.Camelize();
/// <summary>
/// Property names to pascal case (e.g. `PascalCase`).
/// </summary>
public static readonly PropertyNameResolver PascalCase = x => x.Name.Pascalize();
/// <summary>
/// Property names to snake case (e.g. `Snake_Case`).
/// </summary>
public static readonly PropertyNameResolver SnakeCase = x => x.Name.Underscore();
/// <summary>
/// Property names to upper snake case (e.g. `UPPER_SNAKE_CASE`).
/// </summary>
public static readonly PropertyNameResolver UpperSnakeCase = x => x.Name.Underscore().ToUpperInvariant();
/// <summary>
/// Property names to kebab case (e.g. `Kebab-Case`).
/// </summary>
public static readonly PropertyNameResolver KebabCase = x => x.Name.Kebaberize();
/// <summary>
/// Property names to upper kebab case (e.g. `UPPER-KEBAB-CASE`).
/// </summary>
public static readonly PropertyNameResolver UpperKebabCase = x => x.Name.Kebaberize().ToUpperInvariant();
}

0 comments on commit ea75cf6

Please sign in to comment.