解决的JSON.NET合同未应用于内部对象



我正在尝试使用json.net这样的复杂的JSON结构:

{
  "a": 1,
  "b": "value",
  "c": {
    "d": "hello"
  }
}

我需要将值转换器应用于c属性。

我正在使用合同解析器,这看起来像:

public class CustomPropertyResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        IList<JsonProperty> props = base.CreateProperties(type, memberSerialization);
        foreach (JsonProperty prop in props.Where(p => p.PropertyType == typeof(string)))
        {
            PropertyInfo pi = type.GetProperty(prop.UnderlyingName);
            if (pi != null && pi.GetCustomAttribute(typeof(MyCustomAttribute), true) != null)
            {
                prop.ValueProvider = new MyStringValueProvider(pi);
            }
        }
        return props;
    }

如果需要应用的价值提供商的属性在最高级别(例如b),但它对于嵌套值不起作用(d)。CreateProperties根本不被列为嵌套对象。

如何确保合同解析器也将其应用于嵌套对象?

编辑:这是一个完整的最小复制,应该打印" Hello"one_answers" World",但要打印" Olleh"one_answers" Dlrow":

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace JsonNetStackOverflow
{
    public class Program
    {
        public static void Main(string[] args)
        {
            string json = "{'a':'olleh', 'b': { 'c': 'dlrow' } }";
            JsonSerializerSettings settings = new JsonSerializerSettings()
            {
                ContractResolver = new ReversePropertyResolver()
            };
            ClassA result = JsonConvert.DeserializeObject<ClassA>(json, settings);
            Console.WriteLine(result.A);
            Console.WriteLine(result.B.C);
            Console.ReadLine();
        }
    }
    public class ReverseAttribute : Attribute
    { }
    public class ReversePropertyResolver : DefaultContractResolver
    {
        protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
        {
            IList<JsonProperty> props = base.CreateProperties(type, memberSerialization);
            foreach (JsonProperty prop in props.Where(p => p.PropertyType == typeof(string)))
            {
                PropertyInfo pi = type.GetProperty(prop.UnderlyingName);
                if (pi != null && pi.GetCustomAttribute(typeof(ReverseAttribute), true) != null)
                {
                    prop.ValueProvider = new ReverseValueProvider(pi);
                }
            }
            return props;
        }
    }
    public class ReverseValueProvider : IValueProvider
    {
        private readonly PropertyInfo targetProperty;
        public ReverseValueProvider(PropertyInfo targetProperty)
        {
            this.targetProperty = targetProperty;
        }
        public object GetValue(object target)
        {
            string value = (string)targetProperty.GetValue(target);
            return new string(value.Reverse().ToArray());
        }
        public void SetValue(object target, object value)
        {
            targetProperty.SetValue(target, new string(((string)value).Reverse().ToArray()));
        }
    }
    public class ClassA
    {
        public ClassA(string a, ClassB b)
        {
            this.A = a;
            this.B = b;
        }
        [Reverse]
        [JsonProperty("a")]
        public string A { get; set; }
        [JsonProperty("b")]
        public ClassB B { get; set; }
    }
    public class ClassB
    {
        public ClassB(string c)
        {
            this.C = c;
        }
        [Reverse]
        [JsonProperty("c")]
        public string C { get; set; }
    }
}

您的ReverseValueProvider.SetValue()方法未称呼您的类型ClassAClassB的原因是使用参数化的构造函数构造,并且传递的值是您要倒的值:

public class ClassB
{
    public ClassB(string c)
    {
        // You would like c to be reversed but it's not since it's never set via its setter.
        this.C = c;
    }
    [Reverse]
    [JsonProperty("c")]
    public string C { get; set; }
}

因为json.net正在通过构造函数填充这些值,所以它从不调用相应的属性设置器,并且字符串永远不会相反。

要确保调用设置器(因此扭转字符串),您可以在类型的类型中添加私有参数的构造函数,并用[JsonConstructor]标记:

public class ClassA
{
    [JsonConstructor]
    ClassA() {}
    public ClassA(string a, ClassB b)
    {
        this.A = a;
        this.B = b;
    }
    [Reverse]
    [JsonProperty("a")]
    public string A { get; set; }
    [JsonProperty("b")]
    public ClassB B { get; set; }
}
public class ClassB
{
    [JsonConstructor]
    ClassB() { }
    public ClassB(string c)
    {
        this.C = c;
    }
    [Reverse]
    [JsonProperty("c")]
    public string C { get; set; }
}

相关内容

  • 没有找到相关文章

最新更新