DEV Community

Cover image for C# basic JsonConverter tip
Karen Payne
Karen Payne

Posted on

C# basic JsonConverter tip

Introduction

Learn how to properly use a JsonConverter, along with property and global setup for converters.

Before getting started, the converter is intentionally simple. The focus here is proper planning for the data for a specific task, like importing data from a JSON file into a database, in this case, properly formatted.

Sample converter

Reads and converts the JSON string value to ensure the first character to uppercase.

public class UpperCaseFirstCharConverter : JsonConverter<string>
{
    public override bool CanConvert(Type typeToConvert)
        => typeToConvert == typeof(string);

    public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        => (reader.GetString() ?? string.Empty).CapitalizeFirstLetter();

    public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value ?? "Null");
    }
}
Enter fullscreen mode Exit fullscreen mode

Example usage

Proper-case FirstName and LastName from a JSON file.

Sample data

[
  {
    "Id": 1,
    "FirstName": "jose",
    "LastName": "fernandez",
    "BirthDate": "1985-01-01"
  },
  {
    "Id": 2,
    "FirstName": "Miguel",
    "LastName": "loPez",
    "BirthDate": "1970-12-04"
  },
  {
    "Id": 3,
    "FirstName": "angel",
    "LastName": "PEREZ",
    "BirthDate": "1980-09-11"
  }
]
Enter fullscreen mode Exit fullscreen mode

Modal/class

public class Person
{
    public int Id { get; set; }
    public required string FirstName { get; set; }
    public required string LastName { get; set; }
    public DateOnly BirthDate { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

Code

public static void GlobalExample()
{

    SpectreConsoleHelpers.PrintPink();

    string json =
        /*lang=json*/
        """
        [
          {
            "Id": 1,
            "FirstName": "jose",
            "LastName": "fernandez",
            "BirthDate": "1985-01-01"
          },
          {
            "Id": 2,
            "FirstName": "Miguel",
            "LastName": "loPez",
            "BirthDate": "1970-12-04"
          },
          {
            "Id": 3,
            "FirstName": "angel",
            "LastName": "PEREZ",
            "BirthDate": "1980-09-11"
          }
        ]
        """;

    AnsiConsole.MarkupLine("[bold yellow]Original JSON:[/]");
    SpectreConsoleHelpers.PresentJson(json);

    Console.WriteLine("\n");

    AnsiConsole.MarkupLine("[bold blue]Deserialized and Serialized JSON (with capitalized names):[/]");
    var people = JsonSerializer.Deserialize<List<Person>>(json, GlobalJsonOptions);
    var json1 = JsonSerializer.Serialize(people, GlobalJsonOptions);

    SpectreConsoleHelpers.PresentJson(json1);
}

private static readonly JsonSerializerOptions GlobalJsonOptions = new()
{
    Converters = { new UpperCaseFirstCharConverter() },
    WriteIndented = true
};
Enter fullscreen mode Exit fullscreen mode

For ASP.NET Core in Program.cs

/*
 * Register the custom JSON converter globally for all Razor Pages.
 * This ensures that the converter is applied to all JSON serialization
 * and deserialization operations.
 */
builder.Services
    .AddRazorPages()
    .AddJsonOptions(options =>    
    {
        options.JsonSerializerOptions.Converters.Add(
            new UpperCaseFirstCharConverter());
    });
Enter fullscreen mode Exit fullscreen mode

Results from a console project

Results from a console project

Suppose the following data was used, the State property will be changed.

[
  {
    "Id": 1,
    "FirstName": "jose",
    "LastName": "fernandez",
    "State": "CA",
    "BirthDate": "1985-01-01"
  },
  {
    "Id": 2,
    "FirstName": "Miguel",
    "LastName": "loPez",
    "State": "NY",
    "BirthDate": "1970-12-04"
  },
  {
    "Id": 3,
    "FirstName": "angel",
    "LastName": "PEREZ",
    "State": "TX",
    "BirthDate": "1980-09-11"
  }
]
Enter fullscreen mode Exit fullscreen mode

The fix is to annotate only the FirstName and LastName properties with [JsonConverter] attribute, followed by using the code below, which does not add the converter in the options.

public class Customer
{
    public int Id { get; set; }
    [JsonConverter(typeof(UpperCaseFirstCharConverter))]
    public required string FirstName { get; set; }
    [JsonConverter(typeof(UpperCaseFirstCharConverter))]    
    public required string LastName { get; set; }
    public required string State { get; set; }
    public DateOnly BirthDate { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

Code

public static void PropertiesExample()
{

    SpectreConsoleHelpers.PrintPink();

    string json =
        /*lang=json*/
        """
        [
          {
            "Id": 1,
            "FirstName": "jose",
            "LastName": "fernandez",
            "State": "CA",
            "BirthDate": "1985-01-01"
          },
          {
            "Id": 2,
            "FirstName": "Miguel",
            "LastName": "loPez",
            "State": "NY",
            "BirthDate": "1970-12-04"
          },
          {
            "Id": 3,
            "FirstName": "angel",
            "LastName": "PEREZ",
            "State": "TX",
            "BirthDate": "1980-09-11"
          }
        ]
        """;

    AnsiConsole.MarkupLine("[bold yellow]Original JSON:[/]");
    SpectreConsoleHelpers.PresentJson(json);

    Console.WriteLine("\n");

    AnsiConsole.MarkupLine("[bold blue]Deserialized and Serialized JSON (with capitalized names):[/]");
    var people = JsonSerializer.Deserialize<List<Customer>>(json, Options);
    var json1 = JsonSerializer.Serialize(people, Options);

    SpectreConsoleHelpers.PresentJson(json1);
}

private static JsonSerializerOptions Options => new() { WriteIndented = true };
Enter fullscreen mode Exit fullscreen mode

Results

results

Console Source code ASP.NET Core Source code

Summary

The takeaway is that a developer plans properly before starting a task like the converter used here.

Related

Top comments (0)