防止在WebAPI OData v4服务中发出空值

时间:2015-10-17 22:25:03

标签: c# json odata asp.net-web-api

我正在运行WebAPI OData v4服务,我不希望发出空值。例如,当我请求User对象时,将返回以下内容:

"value": [
{
  "FirstName": "John",
  "LastName": "Smith",
  "EmailAddress": "john@smith.com",
  "PasswordHash": null,
  "PhoneNumber": "11234567890",
  "Website": null,
  "Id": "dac9706a-8497-404c-bb5a-ca1024cf213b"
}

由于PasswordHashWebsite字段为空,我希望它们不包含在输出中。我已经在应用程序的注册块中尝试了以下几行,但它们都不起作用:

config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
config.Formatters.JsonFormatter.SerializerSettings.DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate;
config.Formatters.JsonFormatter.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;

以下是Register方法的全部内容。我使用Newtonsoft Json包来处理JSON序列化。

public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        config.SuppressDefaultHostAuthentication();
        config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        config.Routes.MapHttpRoute(
            name: "UploadComplete",
            routeTemplate: "UploadFiles/Complete",
            defaults: new { controller = "UploadFiles", action = "Complete" }
        );

        var builder = new ODataConventionModelBuilder();

        builder.EntitySet<Address>("Addresses");
        builder.EntitySet<Assignment>("Assignments");
        builder.EntitySet<Course>("Courses");
        builder.EntitySet<File>("Files");
        builder.EntitySet<UploadFile>("UploadFiles");
        builder.EntitySet<Organization>("Organizations");
        builder.EntitySet<Submission>("Submissions");
        builder.EntitySet<Term>("Terms");
        builder.EntitySet<User>("Users");

        config.MapODataServiceRoute(
            routeName: "ODataRoute",
            routePrefix: null,
            model: builder.GetEdmModel());

        // Neither of these lines work.
        config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
        config.Formatters.JsonFormatter.SerializerSettings.DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate;
        config.Formatters.JsonFormatter.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
    }

2 个答案:

答案 0 :(得分:4)

感谢Brian Rogers指出我正确的方向,我最终覆盖了ODataEntityTypeSerializer,如此:

public override ODataEntry CreateEntry(SelectExpandNode selectExpandNode, EntityInstanceContext entityInstanceContext)
{
    ODataEntry entry = base.CreateEntry(selectExpandNode, entityInstanceContext);

    // Remove any properties which are null.
    List<ODataProperty> properties = new List<ODataProperty>();
    foreach (ODataProperty property in entry.Properties)
    {
        if (property.Value != null)
        {
            properties.Add(property);
        }
    }

    entry.Properties = properties;
    return entry;
}

然后我使用RaghuRam-Nadiminti's answer中的代码来实现CustomSerializerProvider类,然后我可以在Register中使用它。

答案 1 :(得分:2)

虽然Web API自己使用Json.Net序列化程序,但MediaTypeFormatter for Web API OData使用自己的内部序列化程序,而不是 Json.Net。因此,更改配置中的Json.Net序列化程序设置不会对OData产生任何影响。但是,您似乎可以实现自己的ODataSerializerProviderODataDeserializerProvider类,以使OData使用Json.Net。请参阅JSON.NET as a WebAPI 2 OData serializer vs ODataMediaTypeFormatter作为起点。