问题
I'm running an WebAPI OData v4 service and I don't want null values to be emitted. For example, when I request a User
object, the following is returned:
"value": [
{
"FirstName": "John",
"LastName": "Smith",
"EmailAddress": "john@smith.com",
"PasswordHash": null,
"PhoneNumber": "11234567890",
"Website": null,
"Id": "dac9706a-8497-404c-bb5a-ca1024cf213b"
}
Since the PasswordHash
and Website
fields are null, I'd like them to not be included in the output. I've tried the following lines in the application's Register block, but none of them work:
config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
config.Formatters.JsonFormatter.SerializerSettings.DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate;
config.Formatters.JsonFormatter.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
Below is the full contents of the Register method. I'm using the Newtonsoft Json package to handle the JSON serialization.
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;
}
回答1:
Thanks Brian Rogers for pointing me in the right direction, I ended up overriding ODataEntityTypeSerializer
like so:
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;
}
And then I used code from RaghuRam-Nadiminti's answer to implement a CustomSerializerProvider
class which I could then use in Register
.
回答2:
Although Web API iteself uses the Json.Net serializer, the MediaTypeFormatter for Web API OData uses its own internal serializer which is not Json.Net. Therefore, changing the Json.Net serializer settings in the configuration will not have any effect on OData. However, it does appear that you can implement your own ODataSerializerProvider and ODataDeserializerProvider classes to get OData to use Json.Net. See JSON.NET as a WebAPI 2 OData serializer vs ODataMediaTypeFormatter for a starting point.
来源:https://stackoverflow.com/questions/33192231/prevent-null-values-from-being-emitted-in-a-webapi-odata-v4-service