In case you are using .Net 7 and System.Text.Json
and trying to achieve the same result here's a solution by utilizing DefaultJsonTypeInfoResolver
(found it from another post and simplified it a bit):
1- Define a custom attribute rather than using JsonPropertyName to be used for deserialization:
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = true)]
public sealed class JsonAlternativeNameAttribute : Attribute
{
public JsonAlternativeNameAttribute(string? name) => this.Name = name;
public string? Name { get; private set; }
}
2- Add an extension class with following implementation:
using System.Reflection;
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
using System.Linq;
namespace MyApp.Core.Extension;
public static class JsonSerializationExtensions
{
private static Action<JsonTypeInfo> AlternativeNamesContract() =>
static typeInfo =>
{
if (typeInfo.Kind != JsonTypeInfoKind.Object)
return;
foreach (var property in typeInfo.Properties)
{
if (property.AttributeProvider?.GetCustomAttributes(typeof(JsonAlternativeNameAttribute), true) is { } list && list.Length > 0)
property.Name = list.OfType<JsonAlternativeNameAttribute>().FirstOrDefault()?.Name ?? property.GetMemberName() ?? property.Name;
}
};
private static string? GetMemberName(this JsonPropertyInfo property) => (property.AttributeProvider as MemberInfo)?.Name;
public static JsonSerializerOptions DefaultDeserializerOptions =
new ()
{
TypeInfoResolver = new DefaultJsonTypeInfoResolver
{
Modifiers = { AlternativeNamesContract() }
}
};
public static JsonSerializerOptions DefaultSerializerOptions =
new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
PropertyNameCaseInsensitive = true,
WriteIndented = true
};
}
3- Use the DefaultDeserializerOptions
from the extension class to deserialize your model based on decorated name from JsonAlternativeName attribute
class Foo
{
[JsonAlternativeName("cust-num")]
public string CustomerNumber { get; set; }
[JsonAlternativeName("cust-name")]
public string CustomerName { get; set; }
}
var foo = JsonSerializer.Deserialize<Foo>("your foo json here", JsonSerializationExtensions.DefaultDeserializerOptions);
4- To serialize objects base on the property names you can use your custom JsonSerializerOptions without setting TypeInfoResolver. DefaultSerializerOptions
in the extension class is a sample that can be used here:
var jsonString = JsonSerializer.Serialize(new Foo {CustomerName="Joe", CustomerNumber="123"}, JsonSerializationExtensions.DefaultSerializerOptions);
and the serialization result would be:
{
"customerNumber": "123",
"customerName": "Joe"
}
JsonProperty
and return an anonymous object according to the parameter you passed. something likenew{UserName=uname}
– Penstock