Ana*_*and 2 json.net data-annotations asp.net-core-2.0
[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; }
}
Run Code Online (Sandbox Code Playgroud)
在Startup.cs中...
services
.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
})
.AddAutoMapper(typeof(Startup))
.AddMvcCore()
.AddJsonFormatters()
.AddApiExplorer();
Run Code Online (Sandbox Code Playgroud)
我的期望是看到具有属性legalEntityId和legalEntityName的json,但生成的json具有id和name作为属性。有人可以帮助我如何更改json属性吗?谢谢阿南德
Json.NET当前不支持Microsoft.AspNetCore.Mvc.ModelMetadataTypeAttribute。在问题#1349中:添加对dotnetcore的ModelMetadataType的支持,例如以前版本中支持的MetadataTypeAttribute,但拒绝实现对它的支持的请求。
Json.NET确实支持System.ComponentModel.DataAnnotations.MetadataTypeAttribute,尽管此答案中描述了一些限制,但是即使此属性存在于.Net核心中(不确定是否存在),它也无济于事,因为您正尝试使用派生的元数据类型。类来重命名基本类型的属性,这不是元数据类型信息的预期用法。即以下作品开箱即用(完整的.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; }
}
Run Code Online (Sandbox Code Playgroud)
但是以下内容却没有:
[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; }
}
Run Code Online (Sandbox Code Playgroud)
为什么Json.NET不允许衍生类型元数据信息修改基本类型协定?您将不得不问Newtonsoft,但猜测包括:
Json.NET是基于契约的序列化器,其中每种类型都通过属性指定其契约。并不是说一种类型可以重写另一种类型的合同。
DataContractJsonSerializer并DataContractSerializer以相同的方式工作。
这样做会违反Liskov替代原则。
那么,您有什么选择呢?
您可以序列化一个DTO来代替您的DTOLegalEntity,然后使用automapper之类的方法在之后之间进行映射:
public class LegalEntityDTO
{
[JsonProperty(PropertyName = "LegalEntityId")]
public long Id { get; set; }
[JsonProperty(PropertyName = "LegalEntityName")]
public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)您可以创建一个自定义JsonConverter的LegalEntity必要逻辑。
您可以使用必要的逻辑创建自定义合同解析器,类似于此处的逻辑,例如:
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
样本.Net小提琴。
要直接序列化,请执行以下操作:
var settings = new JsonSerializerSettings
{
ContractResolver = new ModelMetadataTypeAttributeContractResolver(),
};
var json = JsonConvert.SerializeObject(entity, Formatting.Indented, settings);
Run Code Online (Sandbox Code Playgroud)
要将合约解析器安装到Asp.Net Core中,请参见此处。
请注意,我是使用完整的.Net 4.5.1编写的,因此它只是一个原型。.Net Core使用不同的反射API,但是,如果您按此处所述安装System.Reflection.TypeExtensions,我认为它应该可以工作。
| 归档时间: |
|
| 查看次数: |
3498 次 |
| 最近记录: |