简体   繁体   English

将JSON反序列化为通用对象

[英]Deserialising JSON into a generic object

I have a three classes 我有三节课

public class A<T>
{
    public bool Success {get; set;}
    public string Reason {get; set;}
    public T Data {get; set;}
}

public class B
{ 
    public string Token {get; set;}
}

public class C
{
    public int SomeInt {get; set;}
    public string SomeString {get; set;}
    public double SomeDouble {get; set;}
}

I call my web service and pass in A or A to deserialise into like this 我打电话给我的网络服务,然后传入A或A进行反序列化

 async Task<T> MyTask<T>(...) (where T is A<B> or A<C>)

The service works fine and returns some JSON which if I try and to deserialise into a var, I'm getting nothing deserialised 该服务工作正常,并返回一些JSON,如果我尝试将其反序列化为var,则反序列化的内容都没有

To deserialise, I'm using 为了反序列化,我正在使用

 var foo = JsonConvert.DeserializeObject<T>(response.Content);

Is there a limitation to how I can deserialise the object so I can only use a base class rather than this form of class? 我如何反序列化对象是否有限制,所以我只能使用基类,而不能使用这种形式的类?

Yes, you can not just pass A because A is not base class, it is generic class and does not exists on its own. 是的,您不能仅传递A因为A不是基类,它是泛型类,并且不存在。

C# generates generic classes during compile time, which means if you use A<B> in your code, C# will generate something like: C#在编译时生成泛型类,这意味着,如果在代码中使用A<B> ,则C#将生成类似以下内容的代码:

public class generated_A_B
{
    public bool Success { get; set; }
    public string Reason { get; set; }
    public B Data { get; set; }
}

Nothing will be generated for A<C> , if not explicitly used. 如果未明确使用,则不会为A<C>生成任何内容。 Reason is obvious, if you generate classes for every single combination of the A, you will bloat your code. 原因很明显,如果您为A的每个单独的组合生成类,则会使代码code肿。

In your current situation it is better to just call them explicitly 在您当前的情况下,最好只是显式地调用它们

void Main()
{
    CallAB();
    CallAC();
}

A<B> CallAB()
{
    return ServiceCall<A<B>>("/api/ab");
}

A<C> CallAC()
{
    return ServiceCall<A<C>>("/api/ac");
}

If you really want to get "generic" A , you should make A an actual base class and have your API to return the type of Data . 如果您真的想获得“通用” A ,则应将A设为实际的基类,并使用API​​返回Data的类型。 In my example I just use Name of the type, but you probably should use FullName that includes namespace, to avoid name conflicts. 在我的示例中,我只使用类型的Name ,但是您可能应该使用包含名称空间的FullName ,以避免名称冲突。

void Main()
{
    var json = @"
    {
        ""success"": true,
        ""reason"": ""All good"",
        ""type"": ""B"",
        ""data"": {
            ""token"": ""1234-5678""
        }
    }";
    var foo = JsonConvert.DeserializeObject<A>(json);
    var type = Assembly.GetExecutingAssembly().GetTypes().Where(i => i.IsClass && i.Name == foo.Type).FirstOrDefault();
    if (type == null)
    {
        throw new InvalidOperationException(string.Format("Type {0} not found", foo.Type));
    }
    var data = foo.Data.ToObject(type);
}

public class A
{
    public bool Success { get; set; }
    public string Reason { get; set; }
    public string Type { get; set; }
    public JToken Data { get; set; }
}

public class B
{
    public string Token { get; set; }
}

I would recommend either to go for the easy solution: create an intermediate merged your classes B and C , to something like 我建议您选择一种简单的解决方案:创建将您的类BC合并为类似内容的中间体

    public class BC
    {
        public string Token { get; set; }
        public int SomeInt { get; set; }
        public string SomeString { get; set; }
        public double SomeDouble { get; set; }

        public bool IsB => !String.IsNullOrEmpty(Token);

        public B ToB() => new B() { Token = Token };

        public C ToC() => new C() { SomeInt = SomeInt, SomeString = SomeString, SomeDouble = SomeDouble };
    }

Then you can call your service, and convert BC either to B or C : 然后,您可以致电您的服务,并将BC转换为BC

async Task<A<BC>> MyTask<A<BC>>(...)
var abc = await MyTask(...);
if(abc.Data.IsB)
{
    var resB = abc.data.ToB();
}
else
{
    var resC = abc.data.ToC();
}

Or go to the more complicated solution, with some JsonConverter as explained in this answer: 或者使用此答案中介绍的JsonConverter转到更复杂的解决方案:

how to implement custom jsonconverter in json net to deserialize a list of base 如何在json net中实现自定义jsonconverter以反序列化基本列表

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

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