简体   繁体   English

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

[英]JSON.NET Deserialize interface to attribute name

I have a JSON string eg我有一个 JSON 字符串,例如

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

and my class is in the following structure我的班级采用以下结构

[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; }
}

I use a custom auto resolver which just finds a implementation of a interface using autofac (pulled from json.net website)我使用自定义自动解析器,它使用 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;
        }
    }

I then deserialize the json string using然后我使用反序列化json字符串

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

                });

Now when I deserialize the json the first_name gets serialized into the FirstName property but the company_name does not, it just returns null.现在,当我反序列化 json 时,first_name 被序列化为 FirstName 属性,但 company_name 没有,它只返回 null。 When I use the TraceWriter it states that it cannot find a member called company_name on the ICompany interface (which it obviously cannot as that is set on the Company object class)当我使用 TraceWriter 时,它指出它在 ICompany 接口上找不到名为 company_name 的成员(它显然不能,因为它是在 Company 对象类上设置的)

Why is JSON.NET not using the DataMember name from the Company object to deserialize against?为什么 JSON.NET 不使用 Company 对象中的 DataMember 名称进行反序列化? As it knows about the Compmany object from the custom resolver and it creates that object but just with no values inside.因为它知道来自自定义解析器的 Compmany 对象,它创建了该对象,但里面没有任何值。

How can I get it to use the implementation of the interface and not the interface itself?我怎样才能让它使用接口的实现而不是接口本身?

FYI, this is not the whole object and I cannot just change my property to a class instead of an interface.仅供参考,这不是整个对象,我不能将我的属性更改为类而不是接口。 This is just a slimmed down example of what is happening to all the interface objects.这只是所有界面对象发生的事情的精简示例。

I just had the same problem and while searching for an answer I found your old question here.我刚刚遇到了同样的问题,在寻找答案时,我在这里找到了您的旧问题。 Actually the way you asked it got me on the right track and I solved the problem.实际上,你问的方式让我走上了正轨,我解决了问题。 The following works for me:以下对我有用:

I don't use Autofac, so this is pseudocode.我不使用 Autofac,所以这是伪代码。 But it should be enough to understand it:但是理解它应该就足够了:

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;
    }
}

The contract should be created using the concrete implementation that is registered in the dependency container instead of the interface.合约应该使用在依赖容器中注册的具体实现而不是接口来创建。 Resolving the type from the container for the DefaultCreator obviously should still use the interface.从容器中为 DefaultCreator 解析类型显然仍应使用该接口。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM