-1

I want to import json data from within the class which is the target of the deserialization. Is this possible with System.Text.Json without additional mapping? Ideally I would use "this" instead of the generic type parameter. I know that is impossible, but is there a similar option? Here is my test code which works, because it creates the data object only to map it to the property. Ideally, I would not need to instantiate "Test" twice.

public class Test
{
    public string? Bar { get; set; }
    
    public void ImportJson(string payload)
    {
        var data = System.Text.Json.JsonSerializer.Deserialize<Test>(payload);
        Bar = data?.Bar; // Don't want to map
    }
}

string foo = "{ \"Bar\": \"baz\" }";
var t = new Test();
t.ImportJson(foo);
Console.WriteLine(t.Bar);
dbc
  • 104,963
  • 20
  • 228
  • 340
TvdH
  • 1,088
  • 14
  • 29
  • 3
    No, this isn't possible. `Deserialize` can only ever create new instances, there are no overloads that can fill existing instances. As such it makes little sense to offer `ImportJson` as an instance method, just make it `static Test FromJson(string payload)` or suchlike. (Of course when you have that it's a trivial wrapper around `Deserialize`, so probably of no added vlaue.) – Jeroen Mostert Mar 08 '22 at 17:28
  • 2
    You are looking for a `Populate()` method, but, unlike Newtonsoft, there's [no such method built in to System.Text.Json](https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-migrate-from-newtonsoft-how-to#populate-existing-objects). See: [.Net Core 3.0 JsonSerializer populate existing object](https://stackoverflow.com/q/56835040/3744182). In fact that looks to be a duplicate, agree? – dbc Mar 08 '22 at 18:31
  • Agree, it is a duplicate to this question, I did not find it lacking to know the Json.net "Populate()" method. – TvdH Mar 08 '22 at 21:05

1 Answers1

2

you can try something like this

    string foo = "{ \"Bar\": \"baz\" }";
    var t = new Test();
    t.Deserialize(foo);

    Console.WriteLine(t.Instance.Bar);

classes

public static class Util
{
    public static void Deserialize<T>(this T obj, string json) where T : IImportJson<T>
    {
        obj.Instance=System.Text.Json.JsonSerializer.Deserialize<T>(json);
    }
}

public class Test : ImportJson<Test>
{
    public string? Bar { get; set;}
    
}

public interface IImportJson<T>
{
    public T Instance { get; set; }
}
public class ImportJson<T>: IImportJson<T>
{
    public T Instance { get; set; }
}

if class dosn't have many properies, it could be like this too

public interface IImportJson<T>
{
    public void ImportJson (T obj);
}
public class Test : IImportJson<Test>
{
    public string? Bar { get; set; }
    
    public void ImportJson(Test test)
    {
        Bar=test.Bar;
    }
}
Serge
  • 40,935
  • 4
  • 18
  • 45
  • This still requires an additional instance, but looking at this made me realize that I should reorganize my code and use the deserializer to create the only instance, something along the lines of JsonSerializer.Deserialize(foo, type) since type is dynamic in my case. – TvdH Mar 08 '22 at 21:04
  • What do you mean about additional instance? In this demo case you just assign one property and don't keep anything else. – Serge Mar 08 '22 at 21:16
  • I will have "Test" and the encapsulated "Test.Instance" with this. "Test" instantiated with "new" and "Test.Instance" instantiated by the JsonSerializer. However, it does fulfill my original requirement. – TvdH Mar 09 '22 at 06:54