This is a solution for System.Text.Json
Some class generate with DB first:
public class Entity<T>
{
public T Id { get; set; }
public string Name { get; set; }
}
Create MetadataBasedConverter.cs
using System.Reflection;
using System.Text.Json;
namespace Mynamespace.JsonConverter;
public class MetadataBasedConverter : JsonConverter<object>
{
private PropertyInfo[] GetCombinedProperties(Type type)
{
var metadataAttr = type.GetCustomAttribute<MetadataTypeAttribute>();
var metadataProps = metadataAttr?.MetadataClassType.GetProperties() ?? Array.Empty<PropertyInfo>();
var originalProps = type.GetProperties();
return originalProps.Union(metadataProps).ToArray();
}
public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using (JsonDocument doc = JsonDocument.ParseValue(ref reader))
{
object result = (object)Activator.CreateInstance(typeToConvert)!;
var combinedProps = GetCombinedProperties(typeToConvert);
foreach (JsonProperty prop in doc.RootElement.EnumerateObject())
{
foreach (var property in combinedProps)
{
var metaAttr = property.GetCustomAttribute<JsonPropertyNameAttribute>();
var nameToUse = metaAttr?.Name ?? property.Name;
if (prop.Name.Equals(nameToUse, StringComparison.OrdinalIgnoreCase))
{
var actualProperty = typeToConvert.GetProperty(property.Name);
if (actualProperty != null)
{
object? value = JsonSerializer.Deserialize(prop.Value.GetRawText(), actualProperty.PropertyType);
actualProperty.SetValue(result, value);
break;
}
}
}
}
return result;
}
}
public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options)
{
writer.WriteStartObject();
var combinedProps = GetCombinedProperties(value.GetType());
foreach (var property in combinedProps)
{
var metaAttr = property.GetCustomAttribute<JsonPropertyNameAttribute>();
var nameToUse = metaAttr?.Name ?? property.Name;
var actualProperty = value.GetType().GetProperty(property.Name);
if (actualProperty != null)
{
writer.WritePropertyName(nameToUse);
JsonSerializer.Serialize(writer, actualProperty.GetValue(value), actualProperty.PropertyType, options);
}
}
writer.WriteEndObject();
}
public override bool CanConvert(Type typeToConvert)
{
return typeof(object).IsAssignableFrom(typeToConvert);
}
}
Create a partial class, and add a MetadataTypeAttribute and MetadataBasedConverter
[MetadataType(typeof(Metadata))]
[JsonConverter(typeof(MetadataBasedConverter))]
public partial class Entity<T>
{
internal sealed class Metadata
{
[JsonPropertyName("LegalEntityId")]
public long Id { get; set; }
[JsonPropertyName("LegalEntityName")]
public string Name { get; set; }
}
}
LegalEntitydoesn't have anIdorNameproperty. Do those belong to the base class?ModelMetadataTypeto must bepartial.