Friday, December 2, 2022

JsonExtensionDataAttribute in System.Text.Json.Serialization

In this post let's have a look at this nice attribute JsonExtensionDataAttribute that's available in System.Text.Json.Serialization Namespace.

I had a requirement where I have an integration API that connects a client application with a third-party API. The client application is sending some JSON that needs to be sent to the third-party API as is, and at the same time, within the integration API, I need to intercept and read some values in the JSON. The JSON schema can be huge, and the Integration API doesn't really care about the full JSON schema. So how do we define a POCO class having the properties I really care about and let other properties get deserialized/serialized without any data loss.

Let's go by an example.

Consider the following JSON schema.

string jsonString =
    """
    {
        "_id": "57d0a0a676f943a4007e1525",
        "modified": "2022-09-07T23:20:06.949Z",
        "title": "Register",
        "display": "form",
        "type": "form",
        "name": "register",
        "path": "register",
        "components": [
            {
                "label": "First Name",
                "key": "firstName",
                "type": "textfield",
                "placeholder": "",
                "prefix": "",
                "suffix": "",
                "multiple": false
            },
            {
                "label": "Last Name",
                "key": "firstName",
                "type": "textfield",
                "placeholder": "",
                "prefix": "",
                "suffix": "",
                "multiple": false
            }
        ],
        "tags": []
    }
    """;

Now let's say, I only care about _idname and type properties.

I can create a POCO class, something like below.

public class Form
{
    [JsonPropertyName("_id")]
    public string Id { getset; }
 
    public string Name { getset; }
 
    public string Type { getset; }
}

But then the issue is, upon deserialization, I am going to lose some data. And this is where JsonExtensionDataAttribute comes in handy.

public class Form
{
    [JsonPropertyName("_id")]
    public string Id { getset; }
 
    public string Name { getset; }
 
    public string Type { getset; }
 
    [JsonExtensionData]
    public Dictionary<stringobject> JsonExtensionData { getset; }
}

Now when I deserialized the jsonString to Form what's going to happen is, the properties with matching members will get their values and the properties that do not have a matching member will get added to the JsonExtensionData dictionary.

JsonSerializerOptions jsonSerializerOptions = new()
{
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
 
Form form = JsonSerializer.Deserialize<Form>(jsonString, jsonSerializerOptions);

Here if I have a look at the form, it's going to look like this.

Deserialization
You can see that properties with matching members got their values and the rest went into the Dictionary.

And now when I serialize the form, the values in the Dictionary are written back as expected. 

string serializedString = JsonSerializer.Serialize(form, jsonSerializerOptions);
//{
//    "_id": "57d0a0a676f943a4007e1525",
//    "name": "register",
//    "type": "form",
//    "modified": "2022-09-07T23:20:06.949Z",
//    "title": "Register",
//    "display": "form",
//    "path": "register",
//    "components": [
//        {
//            "label": "First Name",
//            "key": "firstName",
//            "type": "textfield",
//            "placeholder": "",
//            "prefix": "",
//            "suffix": "",
//            "multiple": false
//        },
//        {
//            "label": "Last Name",
//            "key": "firstName",
//            "type": "textfield",
//            "placeholder": "",
//            "prefix": "",
//            "suffix": "",
//            "multiple": false
//        }
//    ],
//    "tags": []
//}

Isn't it nice?

Happy Coding.

Regards,
Jaliya

No comments:

Post a Comment