将JSON反序列化为通用对象

时间:2018-04-18 15:34:47

标签: c# json.net deserialization

我有三个班级

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

我打电话给我的网络服务并传入A或A以反序列化为

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

该服务工作正常并返回一些JSON,如果我尝试并反序列化为var,我没有得到任何反序列化

要反序列化,我正在使用

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

我是如何对对象进行反序列化的限制因此我只能使用基类而不是这种形式的类?

2 个答案:

答案 0 :(得分:1)

是的,您不能只传递A因为A不是基类,它是泛型类,并且不存在。

C#在编译期间生成泛型类,这意味着如果在代码中使用A<B>,C#将生成如下内容:

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

如果没有明确使用,A<C>将不会生成任何内容。原因很明显,如果你为A的每个组合生成类,你将会膨胀你的代码。

在您目前的情况下,最好只是明确地调用它们

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

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

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

如果你真的想得到&#34;泛型&#34; A,您应该将A作为实际的基类,并让您的API返回Data的类型。在我的示例中,我只使用该类型的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; }
}

答案 1 :(得分:0)

我建议您选择一个简单的解决方案:创建一个中级合并您的类 def download(): name = 'video' a = 1 with open('download.txt') as f: lines = f.readlines() for line in lines: url = line response = requests.get(url, stream=True) name = name + str(a) filename = name + '.mp4' with open(filename, 'wb') as f: f.write(response.content) a = a + 1 B,类似于

C

然后,您可以致电您的服务,并将 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 }; } 转换为BCB

C

或者转到更复杂的解决方案,其中包含一些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(); } ,如本答案中所述:

how to implement custom jsonconverter in json net to deserialize a list of base