Home > Net >  In C# / .Net 6, how can I dynamically include/exclude properties from the response?
In C# / .Net 6, how can I dynamically include/exclude properties from the response?

Time:08-17

I want to allow a user to determine some optional fields for the response. The example here is simple strings, but in a live example, this could be used to show/not show hundreds or even thousands of lines of complex properties.

Say that I have a class

public class MyClass
{
    public string Foo { get; set; }
    public string Bar { get; set; } 
    public string Baz { get; set; }
}

//By default, I only want to return Foo
//Ex. 1
// GET /myclass
//Returns
{
    Foo = "Hello Foo"
} 

However, I want to allow the user to decide whether to include Bar and Baz. The user could do this

//Ex. 2
// GET /myclass?includeFoo=true&includeBar=true
//Returns 
{
    Foo = "Hello Foo",
    Bar = "Hello Bar",
    Baz = "Hello Baz"
}

or the user could just include one of bar or baz

//Ex 3
// GET /myclass?includeBar=true
//Returns
{
    Foo = "Hello Foo",
    Bar = "Hello Bar"
}

I know that I could use a dynamic object type to accomplish this goal, but is there a way to do that without using dynamic objects?

CodePudding user response:

You could do a null trick and ignore the data as @Serge pointed out, you can also use the (System.Text.Json) JsonExtensionDataAttribute or (Newtonsoft) JsonExtensionDataAttribute

public class MyClass
{   
    public string Baz { get; set; }

    [JsonExtensionData]
    public Dictionary<string, object> ExtraProperties { get; set; }
}

CodePudding user response:

Assuming that you've already handled the processing of the incoming query string to determine the set of included properties, you can construct your response as normal and then do some final processing on it to remove fields from the final response the user hasn't asked for.

Using JSON.NET, you can serialise this "fat" response object into JSON and load it into a JObject. From there, you can use the Remove method to strip out properties from the response you don't want to send back.

Something like this:

//Process the query string into a set of included properties
var propsToInclude = new HashSet<string>().

...

//Serialise into a JObject
var response = new MyClass { .... }
var obj = JObject.Parse(JsonConvert.SerializeObject(response));

//For each property on MyClass, if that property's name is not in the included
//set, remove it from the serialised response 
foreach(var prop in typeof(MyClass).GetProperties())
{
    if(!propsToInclude.Contains(prop.PropertyName))
        obj.Remove(prop.Name);
}

//Send back the stripped-down JSON response
return obj.ToString();

It's not a giant leap from there to extract this into a helper method that accepts a type, an instance of that type, a set of properties to include and returns back JSON with only the requested properties:

public class MyClass
{
    public string Foo { get; set; }
    public string Bar { get; set; }
    public string Baz { get; set; }
}

public string SerialiseObject<T>(T obj, HashSet<string> propsToInclude)
{
    var response = JObject.Parse(JsonConvert.SerializeObject(obj));

    foreach(var prop in typeof(T).GetProperties())
    {
        if (!propsToInclude.Contains(prop.Name))
            response.Remove(prop.Name);
    }

    return response.ToString();
}

var x = new MyClass { Foo = "foo", Bar = "bar", Baz = "baz" };

//{ "Foo": "foo" }
var y = SerialiseObject(x, new HashSet<string> { nameof(MyClass.Foo) });

//{ "Bar": "bar", "Baz": "baz" }
var z = SerialiseObject(x, new HashSet<string> { nameof(MyClass.Bar), nameof(MyClass.Baz) });

CodePudding user response:

You can do this by configuring the serializer. If you are using System.Text.Json then see here for details: https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-ignore-properties?pivots=dotnet-6-0#ignore-all-null-value-properties

If you are using Newtonsoft.Json then the configuration should be similar but it is called NullValueHandling, see here for details: https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_NullValueHandling.htm

  • Related