When I need to call deserializer for the same type inside a long running loop, I prefer to overwrite to existing instance rather than create a new instance every time.
Json.NET has a feature for it: JsonConvert.PopulateObject(string, object)
(I think the target should be the first argument of it, but it doesn't matter.)
For System.Text.Json, its usage might look like this:
using System.Text.Json
var tmp = new MyClass();
JsonSerializer.ParseTo(ref tmp, "{\"some\":\"json\"}");
I found an option ClassMaterializerStrategy that might do similar thing, but it was an internal option. Even if it was not an internal, I believe a direct method like ParseTo would be better.
cc @steveharter
From @tig in https://github.com/dotnet/corefx/issues/42633
I hadn't actually used Json.NET's
ObjectCreationHandlingsupport and may have mis-interpreted what it did. I thought it gave an option for me to deserialize into an existing object instance. E.g. (psuedocode):class Doc{ public string Title; public string Type; } ... // jsonString holds instance where doc.Type = "Foo"; Document doc = new Document() { Title = "Title" }; Deserialize<Document>(doc, jsonString);With this,
docwould havedoc.Title == "Title"and 'doc.Type == "Foo"`.Forgive me if I misunderstood. But this is what I'm looking for. I don't want Deserialization to create a new instance, but update an existing instance.
FWIW, here's my scenario just so y'all have an understanding of why I think this feature is important:
I'm building an app that uses JSON as a config-file format, ala VS Code, Windows Terminal, etc... All the cool kids are doing this. Like those apps, I have a filesystem watcher that watches the .config file for changes. Like those apps, I'd like all my settings to refresh when this happens.
The classes I'm serializing with System.Text.Json are actually some of my Models (in MVVM) which implement INotifyPropertyChanged. My upper layers thus subscribe to property changes.
This all works groovy, except that without System.Text.Json supporting the equivalent of PopulateObject I have to jump through hoops with temporary instances and deep copies. I have it working for now, but would prefer the deserialization to just allow me to pass an existing instance that it would update.
Thanks for listening.
I vote for this one too. If objects' hierarchies are deep with lots of fields/properties; this shall come in handy. Support polymorphic deserialization example looks simple because derived classes only have one property each.
I have a custom converter that writes generic object type name along with bounding types as part of the json. During deserialization, it creates correct object using those two values, and rest of the reading is done by serializer.Populate(.... call. Thinking about converting it into System.Text.Json flavor; looks like I may have to hand roll bunch of code
@reazhaq - this is exactly the scenario we have - I have a custom JsonConverter<object> which examines a type discriminator to instantiate the relevant type.
It then wants to populate the contents of the type it has instantiated, using the default behaviour, otherwise you get into an infinite recursion.
It would be nice to be able to do a JsonDocument.ParseValue() over the reader so I could inspect the document and pull out the discriminator without having to handle the reading ahead myself [we find it generally unsafe to assume that the discriminator is first property on the object], create a Utf8JsonReader _over that document_ to avoid allocating extra buffers, and pass it on to the default ObjectConverter<T> (now we know what T is) to be populated.
With C#8 nullable types, we get a warning for not initializing a non-nullable list, but System.Text.Json doesn't make use of initialized lists and so we can't and therefore can't dismiss the warning. Am I doing something wrong or is that just the way it is for now?
With C#8 nullable types, we get a warning for not initializing a non-nullable list, but
System.Text.Jsondoesn't make use of initialized lists and so we can't and therefore can't dismiss the warning. Am I doing something wrong or is that just the way it is for now?
Our workaround for DTOs is to create an empty constructor (if there isn't one already) and wrap it in:
#nullable disable
public MyClass() {}
#nullable restore
This will stop the analysis for uninitialized properties. We only use this for DTOs where we have knowledge that something in the system stack has already ensured that the property won't be null when deserialized.
The other option is to place the #nullable directives around each property that is marked as non-nullable but isn't initialized. This is more specific, but also more verbose.
Yes, I figured suppressing the warning would be a workaround, but was kind of hopping that it wouldn't be necessary. I wish System.Text.Json would make use of initialized lists, that way I didn't have to deal with it in this way.
Most helpful comment
I vote for this one too. If objects' hierarchies are deep with lots of fields/properties; this shall come in handy. Support polymorphic deserialization example looks simple because derived classes only have one property each.
I have a custom converter that writes generic object type name along with bounding types as part of the json. During deserialization, it creates correct object using those two values, and rest of the reading is done by
serializer.Populate(....call. Thinking about converting it intoSystem.Text.Jsonflavor; looks like I may have to hand roll bunch of code