using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
public class MyCustomResolver : DefaultContractResolver
protected override JsonObjectContract CreateObjectContract(Type objectType)
var contract = base.CreateObjectContract(objectType);
var overrides = ModelMappings.GetMapping(objectType);
foreach (var property in contract.Properties.Concat(contract.CreatorParameters))
if (property.UnderlyingName != null && overrides.TryGetValue(property.UnderlyingName, out var name))
property.PropertyName = name;
public static class ModelMappings
private static Dictionary<Type, Dictionary<string, string>> memberNameToJsonNameMap = new ()
[typeof(Alarm)] = new() {
{nameof(Alarm.AlarmId), "id"},
{nameof(Alarm.AlarmName), "name"},
{nameof(Alarm.RbcType ), "type"},
{nameof(Alarm.MinimumTolerated ), "min"},
{nameof(Alarm.MaximumTolerated ), "max"},
[typeof(Setting)] = new() {
{nameof(Setting.Active), "setting-active"},
{nameof(Setting.OneRun), "setting-oneRun"},
[typeof(Parameter)] = new() {
{nameof(Parameter.Alarms), "alarms"},
{nameof(Parameter.ParameterSetting), "setting"},
public static Dictionary<string, string>? GetMapping(Type type) => memberNameToJsonNameMap.TryGetValue(type, out var d) ? d : null;
public int AlarmId { get; set; }
public string AlarmName { get; set; }
public AlarmType RbcType { get; set; }
public int MinimumTolerated { get; set; }
public int MaximumTolerated { get; set; }
public bool Active { get; set; }
public bool OneRun { get; set; }
public List<Alarm> Alarms { get; set; }
public Setting ParameterSetting { get; set; }
public class ParameterConverter : JsonConverter<Parameter>
record ParameterDTO(List<Alarm> alarms, [property: JsonProperty("setting-active")] bool? Active, [property: JsonProperty("setting-oneRun")] bool? OneRun);
public override void WriteJson(JsonWriter writer, Parameter? value, JsonSerializer serializer)
var dto = new ParameterDTO(value!.Alarms, value.ParameterSetting?.Active, value.ParameterSetting?.OneRun);
serializer.Serialize(writer, dto);
public override Parameter? ReadJson(JsonReader reader, Type objectType, Parameter? existingValue, bool hasExistingValue, JsonSerializer serializer)
var dto = serializer.Deserialize<ParameterDTO>(reader);
existingValue ??= new ();
existingValue.Alarms = dto.alarms;
if (dto.Active != null || dto.OneRun != null)
existingValue.ParameterSetting = new () { Active = dto.Active.GetValueOrDefault(), OneRun = dto.OneRun.GetValueOrDefault() };
public Parameter Parameter { get; set; }
public static void Test()
static void TestRoundTrip()
var settings = new JsonSerializerSettings
DateFormatString = "YYYY-MM-DD",
ContractResolver = new MyCustomResolver { NamingStrategy = new CamelCaseNamingStrategy() },
Converters = { new ParameterConverter() },
var root = JsonConvert.DeserializeObject<RootModel>(json, settings);
var json2 = JsonConvert.SerializeObject(root, Formatting.Indented, settings);
Console.WriteLine("Result of round-tripping {0}:", root);
Console.WriteLine(json2);
static void TestSerialize()
var parameter = new Parameter
new() { AlarmId = 1, AlarmName = "alarm1", RbcType = AlarmType.Five, MinimumTolerated = 0, MaximumTolerated = 2 },
ParameterSetting = new() { Active = true, OneRun = true },
var settings = new JsonSerializerSettings
DateFormatString = "YYYY-MM-DD",
ContractResolver = new MyCustomResolver { NamingStrategy = new CamelCaseNamingStrategy() },
Converters = { new ParameterConverter() },
var json = JsonConvert.SerializeObject(parameter, Formatting.Indented, settings);
Console.WriteLine("Result of serializing a {0}:", parameter);
public static void Main()
Console.WriteLine("Environment version: {0} ({1}), {2}", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , Environment.Version, Environment.OSVersion);
Console.WriteLine("{0} version: {1}", typeof(JsonSerializer).Namespace, typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");