This is my class data structure that I serialize / deserialize:
public class SettingGroup
{
public string name { get; set; }
public string description { get; set; }
public bool visible { get; set; }
public ObservableCollection<SettingGroup> groups { get; set; }
public ObservableCollection<Setting> settings { get; set; }
public SettingGroup()
{
groups = new ObservableCollection<SettingGroup>();
settings = new ObservableCollection<Setting>();
visible = true;
}
}
public class Setting
{
public string name { get; set; }
public string description { get; set; }
public bool visible { get; set; }
public DescriptionVisibility descriptionVisibility { get; set; }
public Dictionary<string, dynamic> configuration { get; set; }
public dynamic settingValue { get; set; }
public SettingType settingType { get; set; }
public SettingControl settingControl { get; set; }
public Setting()
{
visible = true;
configuration = new Dictionary<string, dynamic>();
}
}
I use the following to ensure that only names and parameter values are stored in JSON, the rest are structured inside the application itself and do not need to be saved / loaded via JSON;
private static string safeFileName(string fileName)
{
string regexSearch = new string(Path.GetInvalidFileNameChars()) + " ";
Regex r = new Regex(string.Format("[{0}]", Regex.Escape(regexSearch)));
fileName = r.Replace(fileName, "");
return fileName;
}
public static void saveSettings(this SettingGroup settingGroup, string fileName = "")
{
var jsonResolver = new IgnorableSerializerContractResolver();
jsonResolver.Ignore(typeof(SettingGroup), "visible");
jsonResolver.Ignore(typeof(SettingGroup), "description");
jsonResolver.Ignore(typeof(Setting), "visible");
jsonResolver.Ignore(typeof(Setting), "descriptionVisibility");
jsonResolver.Ignore(typeof(Setting), "configuration");
jsonResolver.Ignore(typeof(Setting), "settingType");
jsonResolver.Ignore(typeof(Setting), "settingControl");
jsonResolver.Ignore(typeof(Setting), "description");
var jsonSettings = new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore, ContractResolver = jsonResolver };
if (string.IsNullOrWhiteSpace(fileName))
fileName = safeFileName(settingGroup.name);
try
{
if (!Directory.Exists(Global.DataDirectory)) Directory.CreateDirectory(Global.DataDirectory);
File.WriteAllText(Path.Combine(Global.DataDirectory, fileName+".json"), JsonConvert.SerializeObject(settingGroup, Newtonsoft.Json.Formatting.Indented, jsonSettings));
}
catch { }
}
public static void loadSettings(this SettingGroup settingGroup, string fileName = "")
{
var jsonResolver = new IgnorableSerializerContractResolver();
jsonResolver.Ignore(typeof(SettingGroup), "visible");
jsonResolver.Ignore(typeof(SettingGroup), "description");
jsonResolver.Ignore(typeof(Setting), "visible");
jsonResolver.Ignore(typeof(Setting), "descriptionVisibility");
jsonResolver.Ignore(typeof(Setting), "configuration");
jsonResolver.Ignore(typeof(Setting), "settingType");
jsonResolver.Ignore(typeof(Setting), "settingControl");
jsonResolver.Ignore(typeof(Setting), "description");
if (string.IsNullOrWhiteSpace(fileName))
fileName = safeFileName(settingGroup.name);
try
{
if (!Directory.Exists(Global.DataDirectory)) Directory.CreateDirectory(Global.DataDirectory);
var serializerSettings = new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Auto, ContractResolver = jsonResolver };
JsonConvert.PopulateObject(File.ReadAllText(Path.Combine(Global.DataDirectory, fileName + ".json")), settingGroup, serializerSettings);
}
catch { }
}
The custom iDefaultContractResolver is the one that I saw as floating around SE, but will still enable it for completeness:
public class IgnorableSerializerContractResolver : DefaultContractResolver
{
protected readonly Dictionary<Type, HashSet<string>> Ignores;
public IgnorableSerializerContractResolver()
{
this.Ignores = new Dictionary<Type, HashSet<string>>();
}
public void Ignore(Type type, params string[] propertyName)
{
if (!this.Ignores.ContainsKey(type)) this.Ignores[type] = new HashSet<string>();
foreach (var prop in propertyName)
{
this.Ignores[type].Add(prop);
}
}
public bool IsIgnored(Type type, string propertyName)
{
if (!this.Ignores.ContainsKey(type)) return false;
if (this.Ignores[type].Count == 0) return true;
return this.Ignores[type].Contains(propertyName);
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
if (this.IsIgnored(property.DeclaringType, property.PropertyName)
|| this.IsIgnored(property.DeclaringType.BaseType, property.PropertyName))
{
property.ShouldSerialize = instance => { return false; };
}
return property;
}
}
, , , , "" , .., , . Json - . , iDefaultContractResolver / , id JSON .
:
SettingGroup Settings = new SettingGroup();
Settings.name = "Application Settings";
Settings.description = "Common application settings.";
SettingGroup generalSettings = new SettingGroup();
generalSettings.name = "General settings";
Settings.groups.Add(generalSettings);
SettingGroup themeSettings = new SettingGroup();
themeSettings.name = "Theme settings";
Settings.groups.Add(themeSettings);
SettingGroup updateSettings = new SettingGroup();
updateSettings.name = "Update settings";
Settings.groups.Add(updateSettings);
SettingGroup startupSettings = new SettingGroup();
startupSettings.name = "Startup settings";
generalSettings.groups.Add(startupSettings);
Setting startWithWindows = new Setting();
startWithWindows.name = "Start IM with Windows";
startWithWindows.settingValue = true;
startWithWindows.settingControl = SettingControl.Checkbox;
startupSettings.settings.Add(startWithWindows);
Setting startMinimized = new Setting();
startMinimized.name = "Start IM minimized";
startMinimized.settingValue = true;
startMinimized.settingControl = SettingControl.Checkbox;
startupSettings.settings.Add(startMinimized);
SettingGroup performanceSettings = new SettingGroup();
performanceSettings.name = "Performance settings";
generalSettings.groups.Add(performanceSettings);
Setting threadPriority = new Setting();
threadPriority.name = "Thread priority";
threadPriority.description = "This setting may not have a noticeible impact on all platforms, especially higer end ones.";
threadPriority.settingValue = 3;
threadPriority.settingControl = SettingControl.Slider;
threadPriority.configuration.Add("lowVal",0);
threadPriority.configuration.Add("highVal", 7);
threadPriority.configuration.Add("interval", 1);
performanceSettings.settings.Add(threadPriority);
Json:
Json, :
{
"name": "Application Settings",
"description": "Common application settings.",
"visible": true,
"groups": [
{
"name": "General settings",
"description": null,
"visible": true,
"groups": [
{
"name": "Startup settings",
"description": null,
"visible": true,
"groups": [],
"settings": [
{
"name": "Start IM with Windows",
"description": null,
"visible": true,
"descriptionVisibility": 0,
"configuration": {},
"settingValue": true,
"settingType": 0,
"settingControl": 0
},
{
"name": "Start IM minimized",
"description": null,
"visible": true,
"descriptionVisibility": 0,
"configuration": {},
"settingValue": true,
"settingType": 0,
"settingControl": 0
}
]
},
{
"name": "Performance settings",
"description": null,
"visible": true,
"groups": [],
"settings": [
{
"name": "Thread priority",
"description": "This setting may not have a noticeible impact on all platforms, especially higer end ones.",
"visible": true,
"descriptionVisibility": 0,
"configuration": {
"lowVal": 0,
"highVal": 7,
"interval": 1
},
"settingValue": 3,
"settingType": 0,
"settingControl": 2
}
]
}
],
"settings": []
},
{
"name": "Theme settings",
"description": null,
"visible": true,
"groups": [],
"settings": []
},
{
"name": "Update settings",
"description": null,
"visible": true,
"groups": [],
"settings": []
},
{
"name": "General settings",
"description": null,
"visible": true,
"groups": [
{
"name": "Startup settings",
"description": null,
"visible": true,
"groups": [],
"settings": [
{
"name": "Start IM with Windows",
"description": null,
"visible": true,
"descriptionVisibility": 0,
"configuration": {},
"settingValue": true,
"settingType": 0,
"settingControl": 0
},
{
"name": "Start IM minimized",
"description": null,
"visible": true,
"descriptionVisibility": 0,
"configuration": {},
"settingValue": true,
"settingType": 0,
"settingControl": 0
}
]
},
{
"name": "Performance settings",
"description": null,
"visible": true,
"groups": [],
"settings": [
{
"name": "Thread priority",
"description": null,
"visible": true,
"descriptionVisibility": 0,
"configuration": {},
"settingValue": 3,
"settingType": 0,
"settingControl": 0
}
]
}
],
"settings": []
},
{
"name": "Theme settings",
"description": null,
"visible": true,
"groups": [],
"settings": []
},
{
"name": "Update settings",
"description": null,
"visible": true,
"groups": [],
"settings": []
}
],
"settings": []
}
, saveSettings, , , ( )
{
"name": "Application Settings",
"groups": [
{
"name": "General settings",
"groups": [
{
"name": "Startup settings",
"groups": [],
"settings": [
{
"name": "Start IM with Windows",
"settingValue": true
},
{
"name": "Start IM minimized",
"settingValue": true
}
]
},
{
"name": "Performance settings",
"groups": [],
"settings": [
{
"name": "Thread priority",
"settingValue": 3
}
]
}
],
"settings": []
},
{
"name": "Theme settings",
"groups": [],
"settings": []
},
{
"name": "Update settings",
"groups": [],
"settings": []
}
],
"settings": []
}
, , , . IE long bool .
{
"name": "Application Settings",
"description": "Common application settings.",
"visible": true,
"groups": [
{
"name": "General settings",
"description": null,
"visible": true,
"groups": [
{
"name": "Startup settings",
"description": null,
"visible": true,
"groups": [],
"settings": [
{
"name": "Start IM with Windows",
"description": null,
"visible": true,
"descriptionVisibility": 0,
"configuration": {},
"settingValue": true,
"settingType": 0,
"settingControl": 0
},
{
"name": "Start IM minimized",
"description": null,
"visible": true,
"descriptionVisibility": 0,
"configuration": {},
"settingValue": true,
"settingType": 0,
"settingControl": 0
}
]
},
{
"name": "Performance settings",
"description": null,
"visible": true,
"groups": [],
"settings": [
{
"name": "Thread priority",
"description": "This setting may not have a noticeible impact on all platforms, especially higer end ones.",
"visible": true,
"descriptionVisibility": 0,
"configuration": {
"lowVal": 0,
"highVal": 7,
"interval": 1
},
"settingValue": 3,
"settingType": 0,
"settingControl": 2
}
]
}
],
"settings": []
},
{
"name": "Theme settings",
"description": null,
"visible": true,
"groups": [],
"settings": []
},
{
"name": "Update settings",
"description": null,
"visible": true,
"groups": [],
"settings": []
},
{
"name": "General settings",
"description": null,
"visible": true,
"groups": [
{
"name": "Startup settings",
"description": null,
"visible": true,
"groups": [],
"settings": [
{
"name": "Start IM with Windows",
"description": null,
"visible": true,
"descriptionVisibility": 0,
"configuration": {},
"settingValue": true,
"settingType": 0,
"settingControl": 0
},
{
"name": "Start IM minimized",
"description": null,
"visible": true,
"descriptionVisibility": 0,
"configuration": {},
"settingValue": true,
"settingType": 0,
"settingControl": 0
}
]
},
{
"name": "Performance settings",
"description": null,
"visible": true,
"groups": [],
"settings": [
{
"name": "Thread priority",
"description": null,
"visible": true,
"descriptionVisibility": 0,
"configuration": {},
"settingValue": 3,
"settingType": 0,
"settingControl": 0
}
]
}
],
"settings": []
},
{
"name": "Theme settings",
"description": null,
"visible": true,
"groups": [],
"settings": []
},
{
"name": "Update settings",
"description": null,
"visible": true,
"groups": [],
"settings": []
}
],
"settings": []
}