In this article, we’ll learn how to use System.Text.Json for camel case serialization in .NET 7.

First, we’ll take a glance at the default behavior when serializing. Then we’ll use two different ways for the camel case serialization. Lastly, we’ll discuss how we can make our code cleaner.

Support Code Maze on Patreon to get rid of ads and get the best discounts on our products!
Become a patron at Patreon!
To download the source code for this article, you can visit our GitHub repository.

Let’s take a look.

Default Serialization Behavior

By default, JsonSerializer will use the same property names when serializing or deserializing with System.Text.Json.

Let’s define a Person class:

public class Person
{
    public string? FirstName { get; set; }
    public string? Surname { get; set; }
    public int? Age { get; set; }
    public bool? IsActive { get; set; }
}

The reason why we are using the nullable type for Age and IsActive is when we deserialize JSON string to a Person object, if  Age or IsActive are not provided, they will be deserialized to the default value (zero and false). But if we define them with the nullable type, they will be deserialized to null, which is what we want here.

If we try to serialize an instance of Person:

var person = new Person()
{
    Age = 20,
    FirstName = "John",
    Surname = "Doe",
    IsActive = true
};
Console.WriteLine($"{JsonSerializer.Serialize(person)}");

When we run the application, we will get the result:

{"FirstName":"John","Surname":"Doe","Age":20,"IsActive":true}

By default, the object can only be serialized or deserialized with the same property names in the JSON string.

But, what if we want to use JSON keys in the camel case in serialization? We have several ways to achieve that.

Use JsonPropertyName Attribute for Camel Case Serialization

One way to implement this is to add an [JsonPropertyName] attribute on properties with specific names. With this approach, we can define another class:

public class PersonWithAttributes
{
    [JsonPropertyName("firstName")]
    public string? FirstName { get; set; }
    
    [JsonPropertyName("surname")]
    public string? Surname { get; set; }
    
    [JsonPropertyName("age")]
    public int? Age { get; set; }
    
    [JsonPropertyName("isActive")]
    public bool? IsActive { get; set; }
}

Next, we can serialize it:

var personWithAttributes = new PersonWithAttributes
{
    Age = 20,
    FirstName = "John",
    Surname = "Doe",
    IsActive = true
};
Console.WriteLine($"{JsonSerializer.Serialize(personWithAttributes)}");

And, we can inspect the result:

{"firstName":"John","surname":"Doe","age":20,"isActive":true}

Notice the different naming convention from the default one.

If we have a JSON string in camel case, after we deserialize it, we can parse it correctly:

var personString = """{"firstName":"John","surname":"Doe","age":20,"isActive":true}""";
var personFromString = JsonSerializer.Deserialize<PersonWithAttributes>(personString);
Console.WriteLine($"{personFromString.FirstName} {personFromString.Surname}({personFromString.IsActive}) is {personFromString.Age}");

Each property will be assigned with correct value:

John Doe(True) is 20

This is quite a simple approach in some situations and it has its pros:

  • Easy to implement
  • We can specify any name we want to use when serializing

But also, this approach comes with obvious cons: we need to set every property’s name one by one manually.

Now let’s take a look at another approach.

Use JsonSerializerOptions Parameter for Camel Case Serialization

Both JsonSerializer.Serialize and JsonSerializer.Deserialize<T> methods have overloads that receive a second parameter of type JsonSerializerOptions, so we can pass it in with a proper configuration.

Let’s take a look at how to use it:

var person = new Person()
{
    Age = 20,
    FirstName = "John",
    Surname = "Doe",
    IsActive = true
};
JsonSerializer.Serialize(person, new JsonSerializerOptions
{
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase
});

By adding a JsonSerializerOptions parameter, we provide a specific naming convention. The result will be the same as the first approach.

Pros of this approach can be:

  • Easy to implement as well
  • Camel case is a built-in naming convention
  • It comes with much more configuration controls when serializing
  • We don’t have to modify entity properties manually

When we choose this approach, some restrictions may raise our concerns:

  • It is hard and tricky to configure naming policy project-wide
  • We have to add the parameter of type JsonSerializerOptions in every method call, which is easy to forget
  • What if we want some naming conventions other than built-in ones

There are ways to solve these issues. In the next section, we will talk about how to resolve the first and the second issue; as for the third, we can define our naming policy, but it’s unrelated to this article so we will ignore that for now.

Make Our Code Cleaner

In the second approach, we must always add the parameter of type JsonSerializerOptions when we want to serialize or deserialize. That is easy to forget and quite annoying to do for every call.

System.Text.Json does not provide a convenient way to configure the naming policy for the whole project. Instead of going with not so easy way to do it, the easier way is to use an extension methods:

public static class JsonSerializerExtensions
{
    public static string SerializeWithCamelCase<T>(this T data)
    {
        return JsonSerializer.Serialize(data, new JsonSerializerOptions
        {
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase
        });
    }

    public static T DeserializeFromCamelCase<T>(this string json)
    {
        return JsonSerializer.Deserialize<T>(json, new JsonSerializerOptions
        {
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase
        });
    }
}

Then we can use our extension method to do serialization:

person.SerializeWithCamelCase();

Or deserialization:

personString.DeserializeFromCamelCase<Person>()

Both methods will give us the correct result, making our code easier to write.

Conclusion

By looking into these two approaches for camel case serialization using System.Text.Json, both methods have pros and cons. Understanding requirements is the first step to choosing which to use or using different techniques for different scenarios.

Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!
Become a patron at Patreon!