【问题标题】:JSON.NET Deserialize interface to attribute nameJSON.NET 反序列化接口到属性名称
【发布时间】:2016-08-08 16:17:41
【问题描述】:

我有一个 JSON 字符串,例如

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

我的班级结构如下

[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 对象,它会创建该对象,但内部没有值。

我怎样才能让它使用接口的实现而不是接口本身?

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

【问题讨论】:

    标签: c# json json.net deserialization datamember


    【解决方案1】:

    我刚刚遇到了同样的问题,在寻找答案时,我在这里找到了你的老问题。实际上,你问它的方式让我走上了正确的轨道,我解决了这个问题。以下对我有用:

    我不使用 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;
        }
    }
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-26
      • 1970-01-01
      相关资源
      最近更新 更多