2

I'm trying to deserialize JSON from a REST service. I'm deserializing the JSON into a struct. The struct contains public properties. I want to hide the basic string/int objects, and use correct objects for each value. In doing this I hid the original properties, and wanted to find a way to populate them despite that. I found a relevant answer here on stackoverflow. The problem is that the private properties don't actually get assigned any value during deserialization.

I then tried to create my own ContractResolver. I found the below code for the CreateProperty(MemberInfo member, MemberSerialization memberSerialization).

var prop = base.CreateProperty(member, memberSerialization);
if (!prop.Writable)
{
    var property = member as PropertyInfo;
    if (property != null)
    {
        var hasPrivateSetter = property.GetSetMethod(true) != null;
        prop.Writable = hasPrivateSetter;
    }
}

return prop;

This still doesn't assign to completely private properties. I'm not sure how to proceed from here, since all the solutions I have been able to find use variations of these two solutions. How should I proceed?

EDIT:

I have created a small example that showcases my issue. https://gist.github.com/Herbstein/9ea14e2a4d95dd5aa4430384bfeeedf3

Community
  • 1
  • 1
Herbstein
  • 309
  • 4
  • 12
  • Please can you create an [MVCE](http://stackoverflow.com/help/mcve) to demonstrate your problem. Currently you are not showing what your models look like, how you are setting the contract resolver to the seriaizer, how you are actually doing the serialization, etc. – RB. Sep 16 '16 at 09:27
  • @RB I'm gonna do that right away. – Herbstein Sep 16 '16 at 09:28
  • @RB. I Have create a small example, that is linked in the OP. The output of the program with all possible configurations is just an empty line. – Herbstein Sep 16 '16 at 09:44

1 Answers1

3

It isn't enough to handle private setters, you have to allow for the property itself being private:

internal class PrivateResolver : DefaultContractResolver {
    protected override IList<JsonProperty> CreateProperties(
        Type type, MemberSerialization memberSerialization
    ) {
        return type
            .GetProperties(BindingFlags.Instance | BindingFlags.NonPublic)
            .Select(p => CreateProperty(p, memberSerialization))
            .ToList();
    }

    protected override JsonProperty CreateProperty(
        MemberInfo member, MemberSerialization memberSerialization
    ) {
        var prop = base.CreateProperty(member, memberSerialization);
        if (!prop.Writable && (member as PropertyInfo)?.GetSetMethod(true) != null) {
            prop.Writable = true;
        }
        return prop;
    }
}

I'd be remiss if I didn't also mention AutoMapper as a more general solution for problems like this. That requires you to declare more classes, but also keeps the types themselves simpler.

Jeroen Mostert
  • 27,176
  • 2
  • 52
  • 85