using System.Collections.Generic;
using Newtonsoft.Json.Linq;
public static void Main()
var employee = new Employee
string json = JsonConvert.SerializeObject(employee, Formatting.Indented, new JsonSerializerSettings
Converters = new List<JsonConverter> { new EvalResultConverter() },
Error = (_, args) => args.ErrorContext.Handled = true,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
public class EvalResultConverter : JsonConverter
public override bool CanRead => false;
public override bool CanWrite => true;
public override bool CanConvert(Type objectType) => true;
public override object ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
=> throw new NotImplementedException();
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
var token = JToken.FromObject(value!);
if (token.Type is JTokenType.Object)
var tokenObject = (JObject)token;
foreach (var property in tokenObject.Properties())
if (property.Value.Type is JTokenType.Object && typeof(Optional).IsAssignableFrom(value!.GetType().GetProperty(property.Name)!.PropertyType))
var propertyObject = (JObject)property.Value;
tokenObject[property.Name] = propertyObject["HasValue"]!.Value<bool>() ? propertyObject["Value"] : null;
tokenObject.WriteTo(writer);
else token.WriteTo(writer);
public bool HasValue { get; set; }
public object Value { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public IList<string> Roles { get; set; }
public Optional HasMiddleName = new Optional
public Optional HasLastName = new Optional
public Optional HasFirstName = new Optional
public Optional HasAcronym = new Optional