[Table("LegalEntity")]
[ModelMetadataType(typeof(LegalEntityMeta))]
public class LegalEntity : Entity<long>
{
}
public class LegalEntityMeta
{
[JsonProperty(PropertyName = "LegalEntityId")]
public long Id { get; set; }
[JsonProperty(PropertyName = "LegalEntityName")]
public string Name { get; set; }
}
在启动中.cs....
services
.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
})
.AddAutoMapper(typeof(Startup))
.AddMvcCore()
.AddJsonFormatters()
.AddApiExplorer();
我的期望是看到具有属性 legalEntityId 和 legalEntityName 的 json,但生成的 json 具有 id 和名称作为属性。 有人可以帮我如何更改 json 属性吗? 谢谢 阿南德
Json.NET 目前不支持Microsoft.AspNetCore.Mvc.ModelMetadataTypeAttribute
。 在问题 #1349:添加对 dotnetcore 的 ModelMetadataType 的支持,就像以前版本中支持的 MetadataTypeAttribute 一样,实现对它的支持的请求被拒绝。
Json.NET 确实支持System.ComponentModel.DataAnnotations.MetadataTypeAttribute
,尽管本答案中描述了一些限制,但是即使此属性存在于 .Net core 中(不确定是否存在),它也无济于事,因为您正在尝试使用派生类的元数据类型来重命名基类型中的属性,这不是元数据类型信息的预期用法。 即以下内容开箱即用(在完整的 .Net 中):
[System.ComponentModel.DataAnnotations.MetadataType(typeof(EntityMeta))]
public class Entity<T>
{
public T Id { get; set; }
public string Name { get; set; }
}
public class EntityMeta
{
[JsonProperty(PropertyName = "LegalEntityId")]
public long Id { get; set; }
[JsonProperty(PropertyName = "LegalEntityName")]
public string Name { get; set; }
}
但以下没有:
[System.ComponentModel.DataAnnotations.MetadataType(typeof(LegalEntityMeta))]
public class LegalEntity : Entity<long>
{
}
public class LegalEntityMeta
{
[JsonProperty(PropertyName = "LegalEntityId")]
public long Id { get; set; }
[JsonProperty(PropertyName = "LegalEntityName")]
public string Name { get; set; }
}
为什么 Json.NET 不允许派生类型元数据信息修改基本类型协定? 你将不得不问Newtonsoft,但猜测包括:
Json.NET 是基于协定的序列化程序,其中每种类型都通过属性指定其协定。 不打算让一种类型重写另一种类型的合约。
DataContractJsonSerializer
和DataContractSerializer
的工作方式相同。这样做会违反利斯科夫替代原则。
那么,您有什么选择?
你可以序列化一个DTO来代替你的
LegalEntity
,并使用类似自动映射器的东西来映射:public class LegalEntityDTO { [JsonProperty(PropertyName = "LegalEntityId")] public long Id { get; set; } [JsonProperty(PropertyName = "LegalEntityName")] public string Name { get; set; } }
您可以使用必要的逻辑为
LegalEntity
创建自定义JsonConverter
。您可以使用必要的逻辑创建自定义合约解析程序,类似于此处的逻辑,例如以下内容:
using System.Reflection; public class ModelMetadataTypeAttributeContractResolver : DefaultContractResolver { public ModelMetadataTypeAttributeContractResolver() { // Default from https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.Formatters.Json/JsonSerializerSettingsProvider.cs this.NamingStrategy = new CamelCaseNamingStrategy(); } const string ModelMetadataTypeAttributeName = "Microsoft.AspNetCore.Mvc.ModelMetadataTypeAttribute"; const string ModelMetadataTypeAttributeProperty = "MetadataType"; protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) { var properties = base.CreateProperties(type, memberSerialization); var propertyOverrides = GetModelMetadataTypes(type) .SelectMany(t => t.GetProperties()) .ToLookup(p => p.Name, p => p); foreach (var property in properties) { var metaProperty = propertyOverrides[property.UnderlyingName].FirstOrDefault(); if (metaProperty != null) { var jsonPropertyAttribute = metaProperty.GetCustomAttributes<JsonPropertyAttribute>().FirstOrDefault(); if (jsonPropertyAttribute != null) { property.PropertyName = jsonPropertyAttribute.PropertyName; // Copy other attributes over if desired. } } } return properties; } static Type GetModelMetadataType(Attribute attribute) { var type = attribute.GetType(); if (type.FullName == ModelMetadataTypeAttributeName) { var property = type.GetProperty(ModelMetadataTypeAttributeProperty); if (property != null && property.CanRead) { return property.GetValue(attribute, null) as Type; } } return null; } static Type[] GetModelMetadataTypes(Type type) { var query = from t in type.BaseTypesAndSelf() from a in t.GetCustomAttributes(false).Cast<System.Attribute>() let metaType = GetModelMetadataType(a) where metaType != null select metaType; return query.ToArray(); } } public static partial class TypeExtensions { public static IEnumerable<Type> BaseTypesAndSelf(this Type type) { while (type != null) { yield return type; type = type.BaseType; } } }
示例 .Net 小提琴。
要直接序列化,请执行以下操作:
var settings = new JsonSerializerSettings { ContractResolver = new ModelMetadataTypeAttributeContractResolver(), }; var json = JsonConvert.SerializeObject(entity, Formatting.Indented, settings);
要将合约解析器安装到 Asp.Net Core 中,请参阅此处。
请注意,我使用完整的.Net 4.5.1编写了此内容,因此它只是一个原型。 .Net Core使用不同的反射API,但是如果你安装System.Reflection.TypeExtensions,我相信它应该可以工作。
切换到Newtonsoft.Json会有所帮助:
-
Add nuget package Microsoft.AspNetCore.Mvc.Newtonsoft.Json
-
在启动中.cs -> 配置服务(有关详细信息,请阅读 https://www.ryadel.com/en/use-json-net-instead-of-system-text-json-in-asp-net-core-3-mvc-projects/)
服务业。AddControllers()。AddNewtonsoftJson();
-
使用 System.Text.Json.Serialization 替换并使用 MetadataType 而不是 ModelMetadataType:
using Newtonsoft.Json; namespace YourDbDataNamespace { [MetadataType(typeof(UserMetadata))] public partial class User {} public class UserMetadata { [JsonProperty(PropertyName = "LegalEntityId")] int Id { get; set; } [JsonIgnore] public string PasswordHash { get; set; } } }