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

本文关键字:属性 接口 NET 反序列化 JSON | 更新日期: 2023-09-27 18:01:24

我有一个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时,它声明它无法在iccompany接口上找到名为company_name的成员(显然不能,因为这是在Company对象类上设置的)

为什么是JSON。. NET不使用来自Company对象的datammember名称来反序列化?因为它从自定义解析器中知道Compmany对象,所以它创建了那个对象,但是里面没有值。

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

仅供参考,这不是整个对象,我不能只是将我的属性更改为类而不是接口。

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

我刚刚遇到了同样的问题,在寻找答案的同时,我在这里发现了你的老问题。实际上你问的方式让我找到了正确的方向,我解决了这个问题。以下内容适合我:

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

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解析类型显然仍然应该使用接口。