use*_*271 165 c# asp.net asp.net-mvc asp.net-web-api
我正在使用MVC 4 Web API和asp.net web forms 4.0来构建一个rest API.它工作得很好:
[HttpGet]
public HttpResponseMessage Me(string hash)
{
HttpResponseMessage httpResponseMessage;
List<Something> somethings = ...
httpResponseMessage = Request.CreateResponse(HttpStatusCode.OK,
new { result = true, somethings = somethings });
return httpResponseMessage;
}
Run Code Online (Sandbox Code Playgroud)
现在我需要阻止一些属性被序列化.我知道我可以在列表上使用一些LINQ并只获取我需要的属性,通常这是一个很好的方法,但在目前的情况下,something对象太复杂了,我需要在不同的方法中使用不同的属性集,所以它是在运行时,更容易标记要忽略的每个属性.
有没有办法做到这一点?
cuo*_*gle 216
的ASP.NET Web API使用Json.Net的默认格式,所以如果你的应用程序仅仅只使用JSON作为数据格式,你可以用[JsonIgnore]忽略属性序列:
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
[JsonIgnore]
public List<Something> Somethings { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
但是,这种方式不支持XML格式.因此,如果您的应用程序必须支持更多XML格式(或仅支持XML),而不是使用Json.Net,则应使用[DataContract]支持JSON和XML的应用程序:
[DataContract]
public class Foo
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
//Ignore by default
public List<Something> Somethings { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
为了更加了解,您可以阅读官方文章.
小智 111
根据ASP.NET Web API中的Web API文档页面JSON和XML序列化,可以显式阻止对属性进行序列化,您可以将其[JsonIgnore]用于Json序列化程序或[IgnoreDataMember]默认的XML序列化程序.
但是在测试中我注意到它[IgnoreDataMember]阻止了XML和Json请求的序列化,因此我建议使用它而不是装饰具有多个属性的属性.
CBo*_*ono 29
您可以采用"选择加入"方式,而不是让所有内容都默认为序列化.在此方案中,只允许序列化您指定的属性.你这样做与DataContractAttribute和DataMemberAttribute,在发现System.Runtime.Serialization命名空间.
将DataContactAttribute被应用到类,并DataMemberAttribute适用于你想成为系列化每个成员:
[DataContract]
public class MyClass {
[DataMember]
public int Id { get; set;} // Serialized
[DataMember]
public string Name { get; set; } // Serialized
public string DontExposeMe { get; set; } // Will not be serialized
}
Run Code Online (Sandbox Code Playgroud)
我敢说这是一种更好的方法,因为它迫使你做出明确的决定,决定通过序列化做什么或不做什么.它还允许您的模型类自己生活在一个项目中,而不依赖于JSON.net只是因为其他地方您碰巧使用JSON.net将它们序列化.
joy*_*ym8 19
这对我有用:创建一个自定义合约解析器,它有一个名为AllowList of string array type的公共属性.在您的操作中,根据操作需要返回的内容修改该属性.
1.创建自定义合同解析程序:
public class PublicDomainJsonContractResolverOptIn : DefaultContractResolver
{
public string[] AllowList { get; set; }
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
properties = properties.Where(p => AllowList.Contains(p.PropertyName)).ToList();
return properties;
}
}
Run Code Online (Sandbox Code Playgroud)
2.使用自定义合同解析器
[HttpGet]
public BinaryImage Single(int key)
{
//limit properties that are sent on wire for this request specifically
var contractResolver = Configuration.Formatters.JsonFormatter.SerializerSettings.ContractResolver as PublicDomainJsonContractResolverOptIn;
if (contractResolver != null)
contractResolver.AllowList = new string[] { "Id", "Bytes", "MimeType", "Width", "Height" };
BinaryImage image = new BinaryImage { Id = 1 };
//etc. etc.
return image;
}
Run Code Online (Sandbox Code Playgroud)
这种方法允许我允许/禁止特定请求,而不是修改类定义.如果您不需要XML序列化,请不要忘记将其关闭App_Start\WebApiConfig.cs的API中如果客户端请求xml而不是json,您的API将返回被阻止的属性.
//remove xml serialization
var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
Run Code Online (Sandbox Code Playgroud)
fox*_*ard 17
我将告诉你两种方法来实现你想要的:
第一种方法:使用JsonProperty属性装饰您的字段,以便跳过该字段的序列化(如果它为null).
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public List<Something> Somethings { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
第二种方式:如果您正在与一些复杂的场景进行协商,那么您可以使用Web Api约定("ShouldSerialize"),以便根据某些特定逻辑跳过该字段的序列化.
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
public List<Something> Somethings { get; set; }
public bool ShouldSerializeSomethings() {
var resultOfSomeLogic = false;
return resultOfSomeLogic;
}
}
Run Code Online (Sandbox Code Playgroud)
WebApi使用JSON.Net并使用反射进行序列化,因此当它检测到(例如)ShouldSerializeFieldX()方法时,名称为FieldX的字段将不会被序列化.
Tim*_*han 16
我迟到了游戏,但是一个匿名的对象可以解决这个问题:
[HttpGet]
public HttpResponseMessage Me(string hash)
{
HttpResponseMessage httpResponseMessage;
List<Something> somethings = ...
var returnObjects = somethings.Select(x => new {
Id = x.Id,
OtherField = x.OtherField
});
httpResponseMessage = Request.CreateResponse(HttpStatusCode.OK,
new { result = true, somethings = returnObjects });
return httpResponseMessage;
}
Run Code Online (Sandbox Code Playgroud)
Kav*_*avi 10
尝试使用IgnoreDataMember属性
public class Foo
{
[IgnoreDataMember]
public int Id { get; set; }
public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
小智 8
只需添加以下内容即可正常工作: [IgnoreDataMember]
在 propertyp 之上,例如:
public class UserSettingsModel
{
public string UserName { get; set; }
[IgnoreDataMember]
public DateTime Created { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这适用于 ApiController。编码:
[Route("api/Context/UserSettings")]
[HttpGet, HttpPost]
public UserSettingsModel UserSettings()
{
return _contextService.GetUserSettings();
}
Run Code Online (Sandbox Code Playgroud)
几乎与greatbear302的答案相同,但我根据请求创建了ContractResolver.
1)创建自定义ContractResolver
public class MyJsonContractResolver : DefaultContractResolver
{
public List<Tuple<string, string>> ExcludeProperties { get; set; }
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
if (ExcludeProperties?.FirstOrDefault(
s => s.Item2 == member.Name && s.Item1 == member.DeclaringType.Name) != null)
{
property.ShouldSerialize = instance => { return false; };
}
return property;
}
}
Run Code Online (Sandbox Code Playgroud)
2)使用自定义合同解析器
public async Task<IActionResult> Sites()
{
var items = await db.Sites.GetManyAsync();
return Json(items.ToList(), new JsonSerializerSettings
{
ContractResolver = new MyJsonContractResolver()
{
ExcludeProperties = new List<Tuple<string, string>>
{
Tuple.Create("Site", "Name"),
Tuple.Create("<TypeName>", "<MemberName>"),
}
}
});
}
Run Code Online (Sandbox Code Playgroud)
编辑:
它没有按预期工作(根据请求隔离解析器).我将使用匿名对象.
public async Task<IActionResult> Sites()
{
var items = await db.Sites.GetManyAsync();
return Json(items.Select(s => new
{
s.ID,
s.DisplayName,
s.Url,
UrlAlias = s.Url,
NestedItems = s.NestedItems.Select(ni => new
{
ni.Name,
ni.OrdeIndex,
ni.Enabled,
}),
}));
}
Run Code Online (Sandbox Code Playgroud)
您也许可以使用 AutoMapper 并使用映射.Ignore(),然后发送映射的对象
CreateMap<Foo, Foo>().ForMember(x => x.Bar, opt => opt.Ignore());
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
130903 次 |
| 最近记录: |