Search code examples
c#json.netodata

OData disable serialization of nullable object


how can i disable serialization of null objects? In my startup.cs i have:

services.AddControllers()
        .AddJsonOptions(options =>
        {
            options.JsonSerializerOptions.PropertyNamingPolicy = null;
            options.JsonSerializerOptions.DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull;
        })
        .AddOData(options =>
        {
            options.Filter().Select().OrderBy().Count().SetMaxTop(serviceSettings.MaxPageSize).SkipToken().AddRouteComponents("api", GetEdmModel());
        });

But still in result json i see "PropName": null

It is possible to use NewtonSoft in Odata? I found someting like this Microsoft.AspNetCore.OData.NewtonsoftJson but I don't know how can I use it.


Solution

  • You can do it using a custom serializer:

    1. Create a serializer:

       public class IngoreNullEntityPropertiesSerializer : ODataResourceSerializer
       {
           public IngoreNullEntityPropertiesSerializer(ODataSerializerProvider provider)
               : base(provider) { }
      
           /// <summary>
           /// Only return properties that are not null
           /// </summary>
           /// <param name="structuralProperty">The EDM structural property being written.</param>
           /// <param name="resourceContext">The context for the entity instance being written.</param>
           /// <returns>The property be written by the serilizer, a null response will effectively skip this property.</returns>
           public override Microsoft.OData.ODataProperty CreateStructuralProperty(IEdmStructuralProperty structuralProperty, ResourceContext resourceContext)
           {
               var property = base.CreateStructuralProperty(structuralProperty, resourceContext);
               return property.Value != null ? property : null;
           }
       }
      
    2. Create a serializer provider:

       public class IngoreNullEntityPropertiesSerializerProvider : ODataSerializerProvider
       {
           private readonly IngoreNullEntityPropertiesSerializer entityTypeSerializer;
           public IngoreNullEntityPropertiesSerializerProvider(IServiceProvider rootContainer)
               : base(rootContainer)
           {
               entityTypeSerializer = new IngoreNullEntityPropertiesSerializer(this);
           }
      
           public override IODataEdmTypeSerializer GetEdmTypeSerializer(Microsoft.OData.Edm.IEdmTypeReference edmType)
           {
               if (edmType.Definition.TypeKind == EdmTypeKind.Entity)
                   return entityTypeSerializer;
               else
                   return base.GetEdmTypeSerializer(edmType);
           }
       }
      
    3. Add the provider to services:

        services.AddControllers()
            .AddOData(opt =>
                 opt.Select()
                 .Expand()
                 .AddRouteComponents("odata", 
                     GetEdmModel(), 
                     conf => conf.AddSingleton<IODataSerializerProvider, IngoreNullEntityPropertiesSerializerProvider>()));
      

    Note: I would not recommend you to do that because your response will be as anonymous. It may cause problems when you use it. Also, some of IDE which can integrate with OData will not, work properly. For example when you put data into excel it will show this error:

    error in excel