首页 文章

JSON.NET反序列化属性名称的接口

提问于
浏览
2

我有一个JSON字符串,例如

{
  "first_name": "Paul"
  "company": {
    "company_name": "Microsoft"
  }
}

我的 class 是以下结构

[DataContract]
class User {
  [DataMember(Name = "first_name")]
  public string FirstName { get; set; }

  [DataMember(Name = "company")]
  public ICompany Company { get; set; }
}

interface ICompany {
  string CompanyName { get; set; }
}

[DataContract]
class Company : ICompany {
  [DataMember(Name = "company_name")]
  public string CompanyName { get; set; }
}

我使用自定义自动解析器,它只是使用autofac找到一个接口的实现(从json.net网站拉出)

public class AutofacContractResolver : DefaultContractResolver
    {
        private readonly IContainer _container;

        public AutofacContractResolver(IContainer container)
        {
            _container = container;
        }

        protected override JsonObjectContract CreateObjectContract(Type objectType)
        {
            JsonObjectContract contract = base.CreateObjectContract(objectType);

            // use Autofac to create types that have been registered with it
            if (_container.IsRegistered(objectType))
            {
                contract.DefaultCreator = () => _container.Resolve(objectType);
            }

            return contract;
        }
    }

然后我使用反序列化json字符串

User user = JsonConvert.DeserializeObject<User>(json, new JsonSerializerSettings
                {
                    ContractResolver = _resolver,

                });

现在,当我反序列化json时,first_name被序列化为FirstName属性,但是company_name没有,它只返回null . 当我使用TraceWriter时,它声明它无法在ICompany接口上找到名为company_name的成员(显然它不能像在Company对象类上设置的那样)

为什么JSON.NET不使用Company对象中的DataMember名称进行反序列化?因为它知道自定义解析器中的Compmany对象,它创建了该对象,但内部没有值 .

如何让它使用接口的实现而不是接口本身?

仅供参考,这不是整个对象,我不能只将属性更改为类而不是接口 . 这只是所有界面对象发生的简单示例 .

1 回答

  • 2

    我遇到了同样的问题,在寻找答案的时候,我发现了你的老问题 . 实际上你问它的方式让我走上正轨,我解决了问题 . 以下适用于我:

    我不使用Autofac,所以这是伪代码 . 但它应该足以理解它:

    public class AutofacContractResolver : DefaultContractResolver
    {
        private readonly IContainer _container;
    
        public AutofacContractResolver(IContainer container)
        {
            _container = container;
        }
    
        protected override JsonObjectContract CreateObjectContract(Type objectType)
        {
            JsonObjectContract contract;
    
            // use Autofac to create types that have been registered with it
            if (_container.IsRegistered(objectType))
            {
                //get the class that is mapped to the interface from autofac
                Type mappedType = _container.GetMappedTypeForRegisteredType(objectType);
    
                //so for example when objectType now contains 'ICompany'
                //then mappedType now should contain 'Company'
    
                //now use the mappedType to create the contract
                contract = base.CreateObjectContract(mappedType);
    
                //but still use the objectType for resolving
                contract.DefaultCreator = () => _container.Resolve(objectType);
            }
            else
                contract = base.CreateObjectContract(objectType);
    
            return contract;
        }
    }
    

    应使用在依赖性容器中注册的具体实现而不是接口来创建 Contract . 从容器中为DefaultCreator解析类型显然仍然应该使用该接口 .

相关问题