Herbstein Herbstein - 2 months ago 19
JSON Question

JSON.NET does not deserialize onto private properties

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

Answer

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.

Comments