基于.Net WebApi的类型和属性的自定义Json序列化
本文关键字:自定义 Json 序列化 属性 类型 Net WebApi 基于 | 更新日期: 2023-09-27 18:28:20
我正在用一个mvc项目构建一个web应用程序,一方面是angularjs,另一方面是Webapi。
我会有很多视图,不想在webApi端创建那么多视图模型变体。
有些视图是项目列表,有些视图是一个项目的详细信息。
我可以为我的应用程序中的每个业务实体创建2个视图模型(轻度/摘要和完整/详细),但我会有很多类,维护或发展可能很困难。
我的想法是创建更少的视图模型,并使用属性来指定我想要的属性。轻结果json或完整的json。
好的,显然还不清楚。请和我在一起
public class BookVM
{
[WebApiRef]
public long Id { get; set; }
[WebApiRef]
public String Title { get; set; }
public DateTime Date { get; set; }
public float Price { get; set; }
public AuthorVM Author { get; set; }
}
public class AuthorVM
{
[WebApiRef]
public long Id { get; set; }
[WebApiRef]
public String Name { get; set; }
public int Age { get; set; }
public String Country { get; set; }
public List<BookVM> Books { get; set; }
[...]
}
对于一个列出书籍的页面,我希望有一个json格式的序列化BookMV列表,如下所示:
[
{
"Id": 1,
"Title": "The Lord of the Rings",
"Date": "29'/07'/1954",
"Price": "23",
"Author": {
"Id": 854,
"Name": "J. R. R. Tolkien"
}
},
{
"Id": 2,
"Title": "The Hobbit",
"Date": "21'/08'/1937",
"Price": "12",
"Author": {
"Id": 854,
"Name": "J. R. R. Tolkien"
}
},
{
"Id": 3,
"Title": "A Game of Thrones",
"Date": "06'/08'/1996",
"Price": "17",
"Author": {
"Id": 157,
"Name": "George R. R. Martin"
}
}
]
对于列出作者的页面:
[
{
"Id": 854,
"Name": "J. R. R. Tolkien",
"books": [
{
"Id": 1,
"Title": "The Lord of the Rings"
},
{
"Id": 2,
"Title": "The Hobit"
}
]
},
{
"Id": 157,
"Name": "George R. R. Martin",
"books": [
{
"Id": 3,
"Title": "A Game of Thrones"
}
]
}
]
对于作者的页面:
{
"Id": 157,
"Name": "George R. R. Martin",
"books": [
{
"Id": 3,
"Title": "A Game of Thrones"
}
]
}
属性[WebApiRef]将定义要包含在附加实体中的属性,但不会用于主类型。
因此,根据被序列化/反序列化的类型,该属性将用于定义在内部的附加实体中保留什么。
我希望这是有意义的。。。
我的问题是我该怎么做才能做到这一点?
我读过关于格式化程序、ContractResolver的文章,我不确定在哪里加载或加载什么。
事实上,它不起作用。
我想我可以创建一个自定义ContractResolver并在那里应用我的序列化逻辑。
问题是如何确定我想要序列化的对象的类型。
我想,我可以在解析器中保存CreateProperty传递的第一个类型。
public class CustomSerializationContractResolver : DefaultContractResolver
{
private Type _serializingType;
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
if (_serializingType == null)
{
_serializingType = member.DeclaringType;
}
JsonProperty property = base.CreateProperty(member, memberSerialization);
if (_serializingType == member.DeclaringType)
{
property.ShouldSerialize = (instance) => true;
}
else if(Attribute.IsDefined(member, typeof(WebApiRefAttribute)))
{
property.ShouldSerialize = (instance) => true;
}
else
{
property.ShouldSerialize = (instance) => false;
}
return property;
}
}
这起到了作用,但没有为每个对象序列化安装约定解析程序。因此,保存的类型对于下一个序列化是不正确的。
我使用的是WebApi,contractResolver是在WebApiConfig.cs中全局设置的它是通过所有控制器方法共享的。
formatter.SerializerSettings.ContractResolver = new CustomSerializationContractResolver();
我发现你可以通过控制器应用ContractResolver,但问题仍然存在,因为你可以通过不同的控制器使用不同的返回类型。
不幸的是,我没有找到通过方法指定ContractResolver的方法。
总之,它不起作用,因为自定义ContractResolver安装一次并使用:
- 通过所有方法(如果全局设置)
- 或由控制器中的每种方法使用(如果由控制器设置)