Repository navigation
Settings deserialization fails if FilterParams.CurrentColumnizer can't be deserialized #470
Description
Activity
I'll have a look seems to be a bug.
This will be part of the rework that the persister now uses json instead of xml.
if you want, you can get the latest version from the branch persister_in_json but it currently does not build, because the implementation is not finished yet
- addedbugPesky little gritter, needs squashingPesky little gritter, needs squashing
on Sep 27, 2025 AndisGrossteins commented
on Sep 27, 2025 ContributorAuthorMore actionsYes, I'm already looking at the branch. Introducing a custom attribute and converter for serializing columnizers seems smart and more robust.
I was pondering a simpler approach using Json.NET error handling event in
ConfigManagerjust to avoid losing all the settings in case one entry can't be deserialized.Also, don't know why the
[field: NonSerialized]property is ignored by Json.NET because documentation on newtonsoft.com says theSystem.NonSerializedAttributeis supported.JSON.net and newtonsoft json are 2 different implementations of the json format. JSON.net does not support everything that newtonsoft does. thats why I use the newtonsoft one
I would like to use the .net one, because it's a native implementation, but it's just not there yet
AndisGrossteins commented
on Sep 27, 2025 ContributorAuthorMore actionsJSON.net and newtonsoft json are 2 different implementations of the json format. JSON.net does not support everything that newtonsoft does. thats why I use the newtonsoft one
Wait, isn't Newtonsoft.Json on GitHub and Json.NET project the same thing? It certainly looks like it is one projet because the website links to the GitHub repo and repo links back to documentation. I guess the only confusion is that project is called Json.NET but repo and namespace is Newtonsoft.Json.
could be that I'm confusing this now with System.Text.Json 😅
this should now work, the snap shot can be downloaded here as artifact https://github.com/LogExperts/LogExpert/actions/runs/18108950348
AndisGrossteins commented
on Sep 30, 2025 ContributorAuthorMore actionsI'm getting an unhandled exception (in a message box) when loading a file with existing XML persistence file and after clicking on "Column restrict" checkbox:
NullReferenceException at LogExpert.UI.Controls.LogWindow.LogWindow.IsFilterSearchDirty(FilterParams filterParams) in D:\a\LogExpert\LogExpert\src\LogExpert.UI\Controls\LogWindow\LogWindow.cs:line 4633 at LogExpert.UI.Controls.LogWindow.LogWindow.CheckForFilterDirty() in D:\a\LogExpert\LogExpert\src\LogExpert.UI\Controls\LogWindow\LogWindow.cs:line 4618 at LogExpert.UI.Controls.LogWindow.LogWindow.OnColumnRestrictCheckBoxCheckedChanged(Object sender, EventArgs e) in D:\a\LogExpert\LogExpert\src\LogExpert.UI\Controls\LogWindow\LogWindow.cs:line 1485 at System.Windows.Forms.CheckBox.set_CheckState(CheckState value) at System.Windows.Forms.CheckBox.OnClick(EventArgs e) at System.Windows.Forms.CheckBox.OnMouseUp(MouseEventArgs mevent) at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.ButtonBase.WndProc(Message& m) at System.Windows.Forms.NativeWindow.Callback(HWND hWnd, MessageId msg, WPARAM wparam, LPARAM lparam)The stack trace is not logged by NLog but just this line:
2025-09-30 22:08:33.9658|FATAL|Program|System.Threading.ThreadExceptionEventArgsAnd another unhandled exception when trying to interact with filter search text comboBox because
filterParams.SearchTextis null:Object reference not set to an instance of an object.\n\n NullReferenceException at LogExpert.UI.Controls.LogWindow.LogWindow.IsFilterSearchDirty(FilterParams filterParams) in D:\a\LogExpert\LogExpert\src\LogExpert.UI\Controls\LogWindow\LogWindow.cs:line 4633 at LogExpert.UI.Controls.LogWindow.LogWindow.CheckForFilterDirty() in D:\a\LogExpert\LogExpert\src\LogExpert.UI\Controls\LogWindow\LogWindow.cs:line 4618 at LogExpert.UI.Controls.LogWindow.LogWindow.OnFilterComboBoxTextChanged(Object sender, EventArgs e) in D:\a\LogExpert\LogExpert\src\LogExpert.UI\Controls\LogWindow\LogWindow.cs:line 2042 at System.Windows.Forms.ComboBox.OnTextChanged(EventArgs e) at System.Windows.Forms.ComboBox.WndProc(Message& m) at System.Windows.Forms.NativeWindow.Callback(HWND hWnd, MessageId msg, WPARAM wparam, LPARAM lparam)This must be related to what I wrote about broken UI when persistence loading fails in PR #472 comment.
I'll have a look tonight
I'm getting an unhandled exception (in a message box) when loading a file with existing XML persistence file and after clicking on "Column restrict" checkbox:
NullReferenceException at LogExpert.UI.Controls.LogWindow.LogWindow.IsFilterSearchDirty(FilterParams filterParams) in D:\a\LogExpert\LogExpert\src\LogExpert.UI\Controls\LogWindow\LogWindow.cs:line 4633 at LogExpert.UI.Controls.LogWindow.LogWindow.CheckForFilterDirty() in D:\a\LogExpert\LogExpert\src\LogExpert.UI\Controls\LogWindow\LogWindow.cs:line 4618 at LogExpert.UI.Controls.LogWindow.LogWindow.OnColumnRestrictCheckBoxCheckedChanged(Object sender, EventArgs e) in D:\a\LogExpert\LogExpert\src\LogExpert.UI\Controls\LogWindow\LogWindow.cs:line 1485 at System.Windows.Forms.CheckBox.set_CheckState(CheckState value) at System.Windows.Forms.CheckBox.OnClick(EventArgs e) at System.Windows.Forms.CheckBox.OnMouseUp(MouseEventArgs mevent) at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.ButtonBase.WndProc(Message& m) at System.Windows.Forms.NativeWindow.Callback(HWND hWnd, MessageId msg, WPARAM wparam, LPARAM lparam)Yeah the reason is, that I don't convert the xml files, because It's unnecessary code, this change is breaking, I will write it in the changelog.
I'll check anyway
I'm getting an unhandled exception (in a message box) when loading a file with existing XML persistence file and after clicking on "Column restrict" checkbox:
NullReferenceException at LogExpert.UI.Controls.LogWindow.LogWindow.IsFilterSearchDirty(FilterParams filterParams) in D:\a\LogExpert\LogExpert\src\LogExpert.UI\Controls\LogWindow\LogWindow.cs:line 4633 at LogExpert.UI.Controls.LogWindow.LogWindow.CheckForFilterDirty() in D:\a\LogExpert\LogExpert\src\LogExpert.UI\Controls\LogWindow\LogWindow.cs:line 4618 at LogExpert.UI.Controls.LogWindow.LogWindow.OnColumnRestrictCheckBoxCheckedChanged(Object sender, EventArgs e) in D:\a\LogExpert\LogExpert\src\LogExpert.UI\Controls\LogWindow\LogWindow.cs:line 1485 at System.Windows.Forms.CheckBox.set_CheckState(CheckState value) at System.Windows.Forms.CheckBox.OnClick(EventArgs e) at System.Windows.Forms.CheckBox.OnMouseUp(MouseEventArgs mevent) at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.ButtonBase.WndProc(Message& m) at System.Windows.Forms.NativeWindow.Callback(HWND hWnd, MessageId msg, WPARAM wparam, LPARAM lparam)The stack trace is not logged by NLog but just this line:
2025-09-30 22:08:33.9658|FATAL|Program|System.Threading.ThreadExceptionEventArgsAnd another unhandled exception when trying to interact with filter search text comboBox because
filterParams.SearchTextis null:Object reference not set to an instance of an object.\n\n NullReferenceException at LogExpert.UI.Controls.LogWindow.LogWindow.IsFilterSearchDirty(FilterParams filterParams) in D:\a\LogExpert\LogExpert\src\LogExpert.UI\Controls\LogWindow\LogWindow.cs:line 4633 at LogExpert.UI.Controls.LogWindow.LogWindow.CheckForFilterDirty() in D:\a\LogExpert\LogExpert\src\LogExpert.UI\Controls\LogWindow\LogWindow.cs:line 4618 at LogExpert.UI.Controls.LogWindow.LogWindow.OnFilterComboBoxTextChanged(Object sender, EventArgs e) in D:\a\LogExpert\LogExpert\src\LogExpert.UI\Controls\LogWindow\LogWindow.cs:line 2042 at System.Windows.Forms.ComboBox.OnTextChanged(EventArgs e) at System.Windows.Forms.ComboBox.WndProc(Message& m) at System.Windows.Forms.NativeWindow.Callback(HWND hWnd, MessageId msg, WPARAM wparam, LPARAM lparam)This must be related to what I wrote about broken UI when persistence loading fails in PR #472 comment.
I got both, Bookmarks should now work, also the Column Restrict should be saved and loaded (was not loaded in the json)
- linked a pull request that will close this issueadded json converter for encoding and bookmarks #474
on Oct 1, 2025 thanks for the remarks, this should be fixed, it's still a breaking changes, since its not longer saved or loaded as xml, if you find anything new, just open a new issue, I'll try to fixed them asap, depending on my time
Thanks for looking into this. I'll pull the changes latest from Development branch and do some tests in a bit.
it's still a breaking changes, since its not longer saved or loaded as xml
IMO, for backwards compatibility the XML deserialization should be kept for at least one release (e.g. till 1.30.0) so that the previously created persistence files are not lost and to save frustrating surprise for users. Of course, persistence serialization would still be done in JSON.
I think I found the cause of of those
NullReferenceExceptions. In at least one case the cause seems to be inPersister.LoadInternal()where it returnsnullif the persistence file doesn't exist but subsequent code tries to access members of the returned object. I don't know if you've fixed that in #474.Sorry but this settings deserialization issue will still persists. At least with custom RegEx columnizer.
On app startup, exception thrown when deserializing settings (JSON path
FilterParams.CurrentColumnizer) because columnizers have not been loaded yet:LogExpert.Config.ConfigManager|Error while deserializing config data: Newtonsoft.Json.JsonSerializationException: Columnizer type 'Apache error log' not found. at LogExpert.Core.Classes.Persister.ColumnizerJsonConverter.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer) in C:\Development\LogExpert\src\LogExpert.Core\Classes\Persister\ColumnizerJsonConverter.cs:line 67 at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType) at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings) at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings) at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value) at LogExpert.Config.ConfigManager.LoadOrCreateNew(FileInfo fileInfo) in C:\Development\LogExpert\src\LogExpert\Config\ConfigManager.cs:line 186
This is the issue I already mentioned in #468.
Settings deserialization fails to instantiate
FilterParams.CurrentColumnizerproperty from JSON pathFilterParams.CurrentColumnizer.Textwhich is"Default (single line)"in the settings.json file.Exception text from log file (version 1.20.0):
The cause of the issue is
[JsonIgnore]attribute onFilterParams.CurrentColumnizerwhich is fromSystem.Text.Json.Serializationbut settings serialization is done withNewtonsoft.Jsonso the attribute is ignored when serializing. Changing the using statement inFilterParams.csfromSystem.Text.Json.SerializationtoNewtonsoft.Jsonfixes the issue but theCurrentColumnizersetting is lost.There are multiple other settings object properties with
[field: NonSerialized]attribute set which must be a leftover from when settings were serialized into binary format. These might be replaced by[JsonIgnore]but I'd like some input regarding this from current project maintainers.