public static void Main()
var a = JsonConvert.SerializeObject(new Foo(new BusinessValue("bar")));
var b = JsonConvert.DeserializeObject<Foo>(@"{""Bar"":""bar""}");
Console.WriteLine($"{b}");
public record Foo(BusinessValue Bar);
[Newtonsoft.Json.JsonConverter(typeof(BusinessValueConverter))]
public record BusinessValue(string Value) : NonEmptyString(Value);
public class BusinessValueConverter : AbstractNewtonsoftJsonConverter<BusinessValue>
protected override BusinessValue Create(string toString) => new(toString);
public abstract class AbstractNewtonsoftJsonConverter<T> : Newtonsoft.Json.JsonConverter<T> where T : NonEmptyString
public override T ReadJson(JsonReader reader, Type objectType, T? existingValue, bool hasExistingValue, JsonSerializer serializer)
return this.Create(reader.Value?.ToString()!);
protected abstract T Create(string toString);
public override void WriteJson(JsonWriter writer, T? value, JsonSerializer serializer)
NonEmptyString a = value!;
writer.WriteValue((string)a);
public record NonEmptyString
private readonly string value;
[Newtonsoft.Json.JsonConstructor]
public NonEmptyString(string value)
if (string.IsNullOrEmpty(value))
throw new ArgumentOutOfRangeException(nameof(value));
public static implicit operator string (NonEmptyString value) => value.value;