using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
using System.Text.Json.Nodes;
public static partial class JsonExtensions
public static Action<JsonTypeInfo> AddPropertyConverter(JsonConverter converter, string propertyName) => typeInfo =>
foreach (var property in typeInfo.Properties.Where(p => converter.CanConvert(p.PropertyType)
&& String.Equals(p.Name, propertyName, StringComparison.Ordinal)))
property.CustomConverter = CustomJsonConverter.Instance;
public static string? GetMemberName(this JsonPropertyInfo property) => (property.AttributeProvider as MemberInfo)?.Name;
public class CustomJsonConverter : JsonConverter<string?>
public static CustomJsonConverter Instance { get; } = new();
public override bool HandleNull => false;
public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) =>
"Modified: " + reader.GetString();
public override void Write(Utf8JsonWriter writer, string? value, JsonSerializerOptions options) =>
writer.WriteStringValue(value);
public record Model(string Foo, string xyz, Nested Nested);
public string Bar {get; set; }
public string xyz {get;set; }
public record Model<T>(string Foo, T xyz, Nested Nested);
public string Bar {get; set;}
public static void Test()
static void TestNonGeneric()
var input = new Model("foo", "xyz", new() { Bar = "bar", xyz = "xyz" });
var json = JsonSerializer.Serialize(input);
string propertyName = "xyz";
JsonSerializerOptions _options = new()
TypeInfoResolver = new DefaultJsonTypeInfoResolver()
Modifiers = {JsonExtensions.AddPropertyConverter(CustomJsonConverter.Instance, propertyName)}
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
PropertyNameCaseInsensitive = true,
var model = JsonSerializer.Deserialize<Model>(json, _options);
var json2 = JsonSerializer.Serialize(model, _options);
Console.WriteLine("Input JSON: {0}", json);
Console.WriteLine("Re-serialized Model: {0}", json2);
Assert.AreEqual(model?.xyz, "Modified: xyz");
Assert.AreEqual(model?.Nested.xyz, "Modified: xyz");
Assert.AreEqual(model?.Foo, "foo");
Assert.AreEqual("""{"Foo":"foo","xyz":"Modified: xyz","Nested":{"Bar":"bar","xyz":"Modified: xyz"}}""", json2);
static void TestGeneric()
var input = new Model<string>("foo", "xyz", new() { Bar = "bar", xyz = "xyz" });
var json = JsonSerializer.Serialize(input);
string propertyName = "xyz";
JsonSerializerOptions _options = new()
TypeInfoResolver = new DefaultJsonTypeInfoResolver()
Modifiers = {JsonExtensions.AddPropertyConverter(CustomJsonConverter.Instance, propertyName)}
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
PropertyNameCaseInsensitive = true,
var model = JsonSerializer.Deserialize<Model<string>>(json, _options);
var json2 = JsonSerializer.Serialize(model, _options);
Console.WriteLine("Input JSON: {0}", json);
Console.WriteLine("Re-serialized {0}: {1}", model?.GetType().Name, json2);
Assert.AreEqual(model?.xyz, "Modified: xyz");
Assert.AreEqual(model?.Nested.xyz, "Modified: xyz");
Assert.AreEqual(model?.Foo, "foo");
Assert.AreEqual("""{"Foo":"foo","xyz":"Modified: xyz","Nested":{"Bar":"bar","xyz":"Modified: xyz"}}""", json2);
public static void Main()
Console.WriteLine("Environment version: {0} ({1}), {2}", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , Environment.Version, Environment.OSVersion);
Console.WriteLine("System.Text.Json version: " + typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");