json.net – 如何使用ASP.Net核心ModelMetadata属性

前端之家收集整理的这篇文章主要介绍了json.net – 如何使用ASP.Net核心ModelMetadata属性前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
  1. [Table("LegalEntity")]
  2. [ModelMetadataType(typeof(LegalEntityMeta))]
  3. public class LegalEntity : Entity<long>
  4. {
  5. }
  6.  
  7. public class LegalEntityMeta
  8. {
  9. [JsonProperty(PropertyName = "LegalEntityId")]
  10. public long Id { get; set; }
  11.  
  12. [JsonProperty(PropertyName = "LegalEntityName")]
  13. public string Name { get; set; }
  14. }

在Startup.cs ….

  1. services
  2. .AddCors(options =>
  3. {
  4. options.AddPolicy("CorsPolicy",builder => builder.AllowAnyOrigin()
  5. .AllowAnyMethod()
  6. .AllowAnyHeader()
  7. .AllowCredentials());
  8. })
  9. .AddAutoMapper(typeof(Startup))
  10. .AddMvcCore()
  11. .AddJsonFormatters()
  12. .AddApiExplorer();

我的期望是看到带有legalEntityId和legalEntityName属性的json,但生成的json有id和name作为属性.
有人请求如何更改json属性
谢谢
阿南德

Json.NET目前不支持 Microsoft.AspNetCore.Mvc.ModelMetadataTypeAttribute.在 Issue #1349: Add support for ModelMetadataType for dotnetcore like supported MetadataTypeAttribute in previous versions,实施支持的请求被拒绝.

Json.NET确实支持System.ComponentModel.DataAnnotations.MetadataTypeAttribute,尽管有一些在this answer中描述的限制,但是即使这个属性出现在.Net核心中(不确定它)它也无济于事,因为你试图使用派生的元数据类型用于重命名基类型属性的类,这不是元数据类型信息的预期用途.即以下工作开箱即用(完整.Net):

  1. [System.ComponentModel.DataAnnotations.MetadataType(typeof(EntityMeta))]
  2. public class Entity<T>
  3. {
  4. public T Id { get; set; }
  5.  
  6. public string Name { get; set; }
  7. }
  8.  
  9. public class EntityMeta
  10. {
  11. [JsonProperty(PropertyName = "LegalEntityId")]
  12. public long Id { get; set; }
  13.  
  14. [JsonProperty(PropertyName = "LegalEntityName")]
  15. public string Name { get; set; }
  16. }

但以下不是:

  1. [System.ComponentModel.DataAnnotations.MetadataType(typeof(LegalEntityMeta))]
  2. public class LegalEntity : Entity<long>
  3. {
  4. }
  5.  
  6. public class LegalEntityMeta
  7. {
  8. [JsonProperty(PropertyName = "LegalEntityId")]
  9. public long Id { get; set; }
  10.  
  11. [JsonProperty(PropertyName = "LegalEntityName")]
  12. public string Name { get; set; }
  13. }

为什么Json.NET不允许派生类型元数据信息来修改基类型契约?你不得不问问牛顿软件,但猜测包括

> Json.NET是一个基于合同的序列化程序,其中每种类型都通过属性指定其合同.并不是说一种类型可以重写第二种类型的合同.
> DataContractJsonSerializer和DataContractSerializer的工作方式相同.
>这样做会违反Liskov substitution principle.

那么,你有什么选择?

>您可以序列化DTO代替您的LegalEntity,并使用类似automapper之类的内容进行映射:

  1. public class LegalEntityDTO
  2. {
  3. [JsonProperty(PropertyName = "LegalEntityId")]
  4. public long Id { get; set; }
  5.  
  6. [JsonProperty(PropertyName = "LegalEntityName")]
  7. public string Name { get; set; }
  8. }

>您可以使用必要的逻辑为LegalEntity创建custom JsonConverter.
>您可以使用必要的逻辑创建custom contract resolver,类似于here,例如:

  1. using System.Reflection;
  2.  
  3. public class ModelMetadataTypeAttributeContractResolver : DefaultContractResolver
  4. {
  5. public ModelMetadataTypeAttributeContractResolver()
  6. {
  7. // Default from https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.Formatters.Json/JsonSerializerSettingsProvider.cs
  8. this.NamingStrategy = new CamelCaseNamingStrategy();
  9. }
  10.  
  11. const string ModelMetadataTypeAttributeName = "Microsoft.AspNetCore.Mvc.ModelMetadataTypeAttribute";
  12. const string ModelMetadataTypeAttributeProperty = "MetadataType";
  13.  
  14. protected override IList<JsonProperty> CreateProperties(Type type,MemberSerialization memberSerialization)
  15. {
  16. var properties = base.CreateProperties(type,memberSerialization);
  17.  
  18. var propertyOverrides = GetModelMetadataTypes(type)
  19. .SelectMany(t => t.GetProperties())
  20. .ToLookup(p => p.Name,p => p);
  21.  
  22. foreach (var property in properties)
  23. {
  24. var MetaProperty = propertyOverrides[property.UnderlyingName].FirstOrDefault();
  25. if (MetaProperty != null)
  26. {
  27. var jsonPropertyAttribute = MetaProperty.GetCustomAttributes<JsonPropertyAttribute>().FirstOrDefault();
  28. if (jsonPropertyAttribute != null)
  29. {
  30. property.PropertyName = jsonPropertyAttribute.PropertyName;
  31. // Copy other attributes over if desired.
  32. }
  33. }
  34. }
  35.  
  36. return properties;
  37. }
  38.  
  39. static Type GetModelMetadataType(Attribute attribute)
  40. {
  41. var type = attribute.GetType();
  42. if (type.FullName == ModelMetadataTypeAttributeName)
  43. {
  44. var property = type.GetProperty(ModelMetadataTypeAttributeProperty);
  45. if (property != null && property.CanRead)
  46. {
  47. return property.GetValue(attribute,null) as Type;
  48. }
  49. }
  50. return null;
  51. }
  52.  
  53. static Type[] GetModelMetadataTypes(Type type)
  54. {
  55. var query = from t in type.BaseTypesAndSelf()
  56. from a in t.GetCustomAttributes(false).Cast<System.Attribute>()
  57. let MetaType = GetModelMetadataType(a)
  58. where MetaType != null
  59. select MetaType;
  60. return query.ToArray();
  61. }
  62. }
  63.  
  64. public static partial class TypeExtensions
  65. {
  66. public static IEnumerable<Type> BaseTypesAndSelf(this Type type)
  67. {
  68. while (type != null)
  69. {
  70. yield return type;
  71. type = type.BaseType;
  72. }
  73. }
  74. }

样品.Net fiddle.

要直接序列化,请执行:

  1. var settings = new JsonSerializerSettings
  2. {
  3. ContractResolver = new ModelMetadataTypeAttributeContractResolver(),};
  4.  
  5. var json = JsonConvert.SerializeObject(entity,Formatting.Indented,settings);

要将合同解析程序安装到Asp.Net Core,请参阅here.

注意我使用完整的.Net 4.5.1编写了这个,所以它只是一个原型. .Net Core使用different reflection API,但如果您按照here所述安装System.Reflection.TypeExtensions,我相信它应该可行.

猜你在找的Json相关文章