Question

How to use class fields with System.Text.Json.JsonSerializer?

I recently upgraded a solution to be all .NET Core 3 and I have a class that requires the class variables to be fields. This is a problem since the new System.Text.Json.JsonSerializer doesn't support serializing nor deserializing fields but only handles properties instead.

Is there any way to ensure that the two final classes in the example below have the same exact values?

using System.Text.Json;

public class Car
{
    public int Year { get; set; } // does serialize correctly
    public string Model; // doesn't serialize correctly
}

static void Problem() {
    Car car = new Car()
    {
        Model = "Fit",
        Year = 2008,
    };
    string json = JsonSerializer.Serialize(car); // {"Year":2008}
    Car carDeserialized = JsonSerializer.Deserialize<Car>(json);

    Console.WriteLine(carDeserialized.Model); // null!
}
 48  24335  48
1 Jan 1970

Solution

 56

In .NET Core 3.x, System.Text.Json does not serialize fields. From the docs:

Fields are not supported in System.Text.Json in .NET Core 3.1. Custom converters can provide this functionality.

In .NET 5 and later, public fields can be serialized by setting JsonSerializerOptions.IncludeFields to true or by marking the field to serialize with [JsonInclude]:

using System.Text.Json;

static void Main()
{
    var car = new Car { Model = "Fit", Year = 2008 };

    // Enable support
    var options = new JsonSerializerOptions { IncludeFields = true };

    // Pass "options"
    var json = JsonSerializer.Serialize(car, options);

    // Pass "options"
    var carDeserialized = JsonSerializer.Deserialize<Car>(json, options);

    Console.WriteLine(carDeserialized.Model); // Writes "Fit"
}

public class Car
{
    public int Year { get; set; }
    public string Model;
}

For details see:

2019-09-27

Solution

 5

If you want this for all MvcControllers in API project you can do similar to this in setup:

builder.Services.AddControllers().AddJsonOptions(options =>
{
    options.JsonSerializerOptions.IncludeFields = true;
});
2023-01-24