There is no way to load or deserialize a JsonDocument
or JsonElement
and convert it to camelCase during the loading process. JsonDocument
and JsonElement
are just read-only, structured views of the utf-8 JSON byte sequence from which they were loaded and as such there's no way to transform the view during (or after) the parsing process. For confirmation, JsonDocument
, JsonElement
and Utf8JsonReader
are all sealed
and JsonElement
has no publicly accessible constructor so there simply isn't an extension point to inject custom transformation of property names.
As an alternative, you could camel-case the property names during re-serialization by creating the following custom JsonConverter<JsonElement>
:
public class JsonElementConverter : JsonConverter<JsonElement>
{
public override void Write(Utf8JsonWriter writer, JsonElement value, JsonSerializerOptions options)
{
switch (value.ValueKind)
{
case JsonValueKind.Object:
var policy = options.PropertyNamingPolicy;
writer.WriteStartObject();
foreach (var pair in value.EnumerateObject())
{
writer.WritePropertyName(policy?.ConvertName(pair.Name) ?? pair.Name);
Write(writer, pair.Value, options);
}
writer.WriteEndObject();
break;
case JsonValueKind.Array:
writer.WriteStartArray();
foreach (var item in value.EnumerateArray())
Write(writer, item, options);
writer.WriteEndArray();
break;
default:
value.WriteTo(writer);
break;
}
}
public override JsonElement Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using var doc = JsonDocument.ParseValue(ref reader);
return doc.RootElement.Clone();
}
}
And then re-serializing your JsonDocument.RootElement
using JsonSerializer
like so:
using var doc = JsonDocument.Parse(jsonString);
JsonNamingPolicy policy = JsonNamingPolicy.CamelCase;
var options = new JsonSerializerOptions
{
Converters = { new JsonElementConverter() },
PropertyNamingPolicy = policy,
WriteIndented = true // Or false, if you prefer
};
var serialized = JsonSerializer.Serialize(doc.RootElement, options);
Notes:
Be sure to serialize the JsonDocument.RootElement
rather than the JsonDocument
. If you serialize the document directly the converter is never invoked.
In .NET 6 it should be possible to transform the property names during deserialization/loading using a custom converter by deserializing to the new JsonNode
DOM, whose elements can be constructed and modified directly by applications code.
As an alternative, if you don't require use of JsonElement
, you could consider deserializing to an ExpandoObject
or similar and remapping the properties during deserialization by extending ObjectAsPrimitiveConverter
from this answer to C# - Deserializing nested json to nested Dictionary<string, object> to do the necessary name transformation.
Demo fiddle here.