.Net Core 3.0 JsonSerializer populate existing obj

2020-02-17 08:33发布

I'm preparing a migration from ASP.NET Core 2.2 to 3.0.

As I don't use any more advanced JSON features (but maybe one as described below), and 3.0 now comes with a built-in namespace/classes for JSON, System.Text.Json, I decided to see if I could drop the previous default Newtonsoft.Json. Do note, I'm aware that System.Text.Json will not completely replace Newtonsoft.Json.

I managed to do that everywhere, e.g.

var obj = JsonSerializer.Parse<T>(jsonstring);

var jsonstring = JsonSerializer.ToString(obj);

but in one place, where I populate an existing object.

With Newtonsoft.Json one can do

JsonConvert.PopulateObject(jsonstring, obj);

The built-in System.Text.Json namespace has some additional classes, like JsonDocumnet, JsonElement and Utf8JsonReader, though I can't find any that take an existing object as a parameter.

Nor am I experienced enough to see how to make use of the existing one's.

There might be a possible upcoming feature in .Net Core (thanks to Mustafa Gursel for the link), but meanwhile (and what if it doesn't),...

...I now wonder, is it possible to achieve something similar as what one can do with PopulateObject?

I mean, is it possible with any of the other System.Text.Json classes to accomplish the same, and update/replace only the properties set?,... or some other clever workaround?


Here is a sample of how it could look like (and it need to be generic as the object passed into the deserialization method is of type <T>). I have 2 Json string's to be parsed into an object, where the first have some default properties set, and the second some, e.g.

Note, a property value can be of any other type than a string.

Json string 1:

{
  "Title": "Startpage",
  "Link": "/index",
}

Json string 2:

{
  "Head": "Latest news"
  "Link": "/news"
}

Using the 2 Json strings above, I want an object resulting in:

{
  "Title": "Startpage",
  "Head": "Latest news",
  "Link": "/news"
}

As seen in above sample, if properties in the 2nd has values/is set, it replace values in the 1st (as with "Head" and "Link"), if not, existing value persist (as with "Title")

7条回答
Anthone
2楼-- · 2020-02-17 09:25

I do not know much about this new version of the plug-in, however I found a tutorial that can be followed tutorial with some examples

Based on him I thought of this method and I imagine that he is able to solve his problem

//To populate an existing variable we will do so, we will create a variable with the pre existing data
object PrevData = YourVariableData;

//After this we will map the json received
var NewObj = JsonSerializer.Parse<T>(jsonstring);

CopyValues(NewObj, PrevData)

//I found a function that does what you need, you can use it
//source: https://stackoverflow.com/questions/8702603/merging-two-objects-in-c-sharp
public void CopyValues<T>(T target, T source)
{

    if (target == null) throw new ArgumentNullException(nameof(target));
    if (source== null) throw new ArgumentNullException(nameof(source));

    Type t = typeof(T);

    var properties = t.GetProperties(
          BindingFlags.Instance | BindingFlags.Public).Where(prop => 
              prop.CanRead 
           && prop.CanWrite 
           && prop.GetIndexParameters().Length == 0);

    foreach (var prop in properties)
    {
        var value = prop.GetValue(source, null);
        prop.SetValue(target, value, null);
    }
}
查看更多
登录 后发表回答