Search code examples
c#.netserializationjson.net

How to set value of certain property on deserialization?


I have a class with properties that setters depend on VeryImportantProperty. But the property shouldn't be serialized by design.

So, when I receive JSON, I have to set VeryImportantProperty during deserialization and before setting other properties.

I suppose it could be done by modifying ContractResolver. I store value for VeryImportantProperty there, but I don't know how to assign it

I tried to use following ContractResolver, but it does not affect

public class MyContractResolver : DefaultContractResolver
{
    public VeryImportantClass VeryImportantPropertyValue { get; set; }
        
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);
            
        if (property.PropertyName == "VeryImportantProperty" && VeryImportantPropertyValue != null)
        {
            property.DefaultValue = VeryImportantPropertyValue;
            property.DefaultValueHandling = DefaultValueHandling.Populate;
            property.Order = -1;
        }

        return property;
    }
}

Solution

  • I solved the problem by creating ContractResolver that overrides CreateContract to set Converter to custom one that overrides Create to pass my VeryImportantProperty to constructor

    Code:

    public class MyContractResolver : DefaultContractResolver
    {
        public VeryImportantClass VeryImportantPropertyValue { get; set; }
    
        protected override JsonContract CreateContract(Type objectType)
        {
            var contract = base.CreateContract(objectType);
            if (VeryImportantPropertyValue == null)
                return contract;
    
            // Solution for multiple classes is commented
            if (objectType == typeof(ContainerClass)/* || objectType.IsSubclassOf(typeof(BaseContainer))*/)
            {
                contract.Converter = new ImportantClassConverter(VeryImportantPropertyValue);
            }
            return contract;
        }
    
        private class ImportantClassConverter: CustomCreationConverter<VeryImportantClass>
        {
            public EntityConverter(VeryImportantClass veryImportantPropertyValue)
            {
                _veryImportantPropertyValue= veryImportantPropertyValue;
            }
    
            private readonly VeryImportantClass _veryImportantPropertyValue;
    
            public override VeryImportantClass Create(Type objectType)
            {
                // Might be simplified but it was used for multiple container classes with one parent
                return objectType.GetConstructor(new[] { typeof(ContainerClass) })
                    ?.Invoke(new[] { _veryImportantPropertyValue }) as ContainerClass;
            }
        }
    }