0

I have a question regarding the newly released .NET Core 3.0 and its new System.Text.Json, I would like to ask if the new JsonDocument could be used similarly to ContractResolver class in Newtonsoft JSON.NET.

What I need is quite straightforward, assume one class with two properties

public string Name {get; set;}
public string Street {get; set;}

and I need to deserialize two different JSONs into this class.

JSON 1:

{"person_A":{"full-name":"Micheal","address-street":"1st avenue","address-city":"New York"},
"person_B":{"full-name":"John","address-street":"Green street","address-city":"London"}}

JSON 2:

{"man_A":{"fullname":"Bush","street":"1st avenue","city":"Washington","state":"US"},
"woman_B":{"fullname":"McCarter","street":"Green street","city":"London","state":"GB"}}

I need to deserialize property full-name, fullname as Name and address-street,street as Street. The other JSON fields are not needed.

To deserialize multiple JSON with different property names I am using a ContractResolver in JSON.NET, which works quite well.

The reason why I am looking into the JsonDocument is that I am deserializing just few JSON properties and with current approach I have to cache entire JSON. If I uderstood correctly, the JsonDocument should allow me to access just the properties I need.

Thanks!

EDIT

To clarify a bit what I am trying to ask here - the idea is to get info about the Json object but not to load it entirely since it is not needed, that's why I would like to use the new JsonDocument, select just the things that I need and load those. Since the Json property names are different than my class properties and I have multiple Json trying to deserialize into the same class, I need something like IContractResolver to match the class properties with the names in Json.

I was able to make something like this working, but I admit it is not very pretty.


private readonly Dictionary propertyMappings = new Dictionary();

private void AddMap<U>(Expression<Func<Instrument,U>> expression, string jsonPropertyName)
            {
                var memberExpression = (MemberExpression)expression.Body;
                propertyMappings.Add(memberExpression.Member.Name, jsonPropertyName);
            }

public override async Task<List<Person>> GetPeopleAsync(HttpRequestMessage request)
    {

    AddMap(x => x.Name, "full-name");
    AddMap(x => x.Street, "address-street");

    var result = new List<Person>();

    var response = await SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
    var stream = await response.Content.ReadAsStreamAsync();
    var document = await JsonDocument.ParseAsync(stream);

    document.RootElement.GetProperty("people").EnumerateObject()
        .ToList()
        .ForEach(x =>
        {
            var person= new Person();

            foreach (var p in propertyMappings)
            {
                x.Value.TryGetProperty(p.Value, out var prop);
                var v = person.GetType().GetProperty(p.Key);
                v.SetValue(person,Convert.ChangeType(prop.ToString(),v.PropertyType));
            }

            result.Add(person);
        });

      return result;
    }</code>
dbc
  • 104,963
  • 20
  • 228
  • 340
AltairMS
  • 1
  • 2
  • Not sure I understand the question, are you asking whether a [`JsonDocument`](https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsondocument?view=netcore-3.0) can be used as a [custom `IContractResolver`](https://www.newtonsoft.com/json/help/html/contractresolver.htm#CustomIContractResolverExamples)? That doesn't really make sense to me as a contract resolver is *not a JSON document* it is a set of rules for how to map JSON from and to .Net objects. – dbc Oct 10 '19 at 22:22
  • Or are you asking, *is there an equivalent to a custom `IContractResolver` in the `System.Text.Json` namespace*? – dbc Oct 10 '19 at 22:23
  • Also, can you also clarify whether your "one class" corresponds to the *entire JSON* or just the values of `"person_A"`, `"person_B"`, `"man_A"` and `"woman_B"`? – dbc Oct 10 '19 at 22:26
  • If you are looking for the equivalent to a custom contract resolver in `System.Text.Json`, it seems that nothing is currently exposed publicly. If you could please [edit] your question to clarify, I can explain, and give some workaround options. – dbc Oct 11 '19 at 18:45
  • Thanks for the comments, I edited the question, hope it helps a bit to clarify what I am trying to do. – AltairMS Oct 14 '19 at 20:57
  • The classes that correspond to `IContractResolver` are [`JsonClassInfo`](https://github.com/dotnet/corefx/blob/master/src/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.cs) and [`JsonPropertyInfo`](https://github.com/dotnet/corefx/blob/master/src/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfo.cs). Unfortunately they are both **`internal`**, so you can't tweak them as you could in Json.NET. Your current workaround isn't bad; you could also do something with custom DTOs + automapper. – dbc Oct 14 '19 at 23:24

0 Answers0