In our web API we have legacy entities that have abbreviated names. We are also using code generation via T4 templates, where we like to keep things simple and predictable:
The JSON response from the web API however does some magic on deciding which letters to convert to lowercase, instead of only the expected first character.
For example, when starting a new default web API in Visual Studio and adding two properties to the WeatherForecast.cs
:
public string TSTValue { get; set; }
public string TSTVL1 { get; set; }
The result is:
[
{
...
"tstValue":null,
"tstvL1":null
},
{
...
"tstValue":null,
"tstvL1":null
}
]
The expected/desired output would be a result with the camelcase property names:
[
{
...
"tSTValue":null,
"tSTVL1":null
},
{
...
"tSTValue":null,
"tSTVL1":null
}
]
How can the magic behavior be overridden?
Firstly the behavior you describe is intended. You can view the source code on Github https://github.com/dotnet/runtime/blob/master/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonCamelCaseNamingPolicy.cs Thankfully the name serialization can be customized with relative ease.
Since you specified that you don't want to use attributes you can create your own JsonNamingPolicy
which can be used to serialize the field names in anyway you see fit.
Below I have created a basic class which ensures that the first character is lower case and leaves the rest of the field string alone. ConvertName(string name)
will be called for each field in the serialized class. In your example that is TSTValue
and TSTVL1
public class JsonFirstCharToLowerNamingPolicy : JsonNamingPolicy
{
public override string ConvertName(string name)
{
// if the string is empty or the first character is already lowercase just return as is
if (string.IsNullOrEmpty(name) || char.IsLower(name[0]))
return name;
char[] chars = name.ToCharArray(); // get a list of chars
chars[0] = char.ToLowerInvariant(chars[0]); // make the first character lower case
// leave the rest of the characters alone or do more processing on it?
return new string(chars); // return the altered string
}
}
To use the class you would simply just have to set the JsonSerializerOptions
of the JsonSerializerOptions
as shown below.
var serializeOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = new JsonFirstCharToLowerNamingPolicy(),
WriteIndented = true
};
var jsonString = JsonSerializer.Serialize(weatherForecast, serializeOptions);