重写自定义协定 JSON.net 协定解析程序中的属性值



我正在尝试实现一个自定义 JSON.net IContractResolver,它将用指定的字符串替换所有空属性值。我知道此功能可以通过序列化类型成员的属性获得;这是我们正在考虑的替代路线。

到目前为止,我的解析器实现如下。StringValueProvider 是 IValueProvider 的简单实现,它不会影响问题,即我无法弄清楚如何获取property的值,因为我对提供member的实例的此方法一无所知,所以我无法将其作为参数传递给GetValue()(在代码示例中标记为 WHAT-GOES-HERE?

有没有办法从memberproperty那里得到我需要的东西?

public class NullSubstitutionPropertyValueResolver : DefaultContractResolver
{
    private readonly string _substitutionValue;
    public NullSubstitutionPropertyValueResolver(string substitutionValue)
    {
        _substitutionValue = substitutionValue;
    }
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty result = base.CreateProperty(member, memberSerialization);
        PropertyInfo property = member as PropertyInfo;
        if (property == null)
        {
            return result;
        }
        // What do I use here to get the property value?
        bool isNull = property.GetValue(WHAT-GOES-HERE?) == null;
        if (isNull)
        {
            result.ValueProvider = new StringValueProvider(_substitutionValue);
        }
        return result;
    }
}

合约解析器不关心实例,它关心类型。 值提供程序与实例有关。 在协定解析程序中,您可以根据属性类型决定是否应将值提供程序应用于属性(例如,也许您只想对string属性使用StringValueProvider? 然后,使值提供程序存储对属性的引用(将其与替换值一起传递到构造函数中)。 在值提供程序中,可以从对象实例中读取值,检查它是否为 null 并执行适当的值替换。

代码应如下所示:

public class NullSubstitutionPropertyValueResolver : DefaultContractResolver
{
    private readonly string _substitutionValue;
    public NullSubstitutionPropertyValueResolver(string substitutionValue)
    {
        _substitutionValue = substitutionValue;
    }
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty result = base.CreateProperty(member, memberSerialization);
        PropertyInfo property = member as PropertyInfo;
        if (property.PropertyType == typeof(string))
        {
            result.ValueProvider = new StringValueProvider(property, _substitutionValue);
        }
        return result;
    }
}
public class StringValueProvider : IValueProvider
{
    private PropertyInfo _targetProperty;
    private string _substitutionValue;
    public StringValueProvider(PropertyInfo targetProperty, string substitutionValue)
    {
        _targetProperty = targetProperty;
        _substitutionValue = substitutionValue;
    }
    // SetValue gets called by Json.Net during deserialization.
    // The value parameter has the original value read from the JSON;
    // target is the object on which to set the value.
    public void SetValue(object target, object value)
    {
        _targetProperty.SetValue(target, value);
    }
    // GetValue is called by Json.Net during serialization.
    // The target parameter has the object from which to read the value;
    // the return value is what gets written to the JSON
    public object GetValue(object target)
    {
        object value = _targetProperty.GetValue(target);
        return value == null ? _substitutionValue : value;
    }
}

这是一个工作演示:https://dotnetfiddle.net/PAZULK

相关内容

最新更新