首页 > 解决方案 > 将 json 反序列化为具有泛型类型的基础对象

问题描述

我有允许您指定泛型类型的 ac# 类。我希望能够重用这个类来消除所有对象将共享的 json 包装器的噪音,这是一个value保存我需要的数据的属性。

如果可重用类具有这样的属性,value那么我就迈出了第一步。但是我在反序列化为提供的泛型类型时遇到了麻烦,因为当我转换它时,它总是返回null. 我知道这是因为value反序列化后的实际类型可能JObject或相似,我完全忘记了类型。您可以在我的演示应用程序中看到它确实抓取了所有数据,但我不能将它转换为我的泛型类型,因为它实际上还不是那种类型。

var get1 = JsonConvert.DeserializeObject<BaseResponse<NameObj>>("{ value: {...} }");
var name1 = get1.Get();//name1 is null

var getList1 = JsonConvert.DeserializeObject<BaseResponse<NameObj>>("{ value: [{...}] }");
var nameList = getList1.List();//nameList is null

public class BaseResponse<T> where T : BaseObj
{
    public object value;

    public T Get()
    {
        return value as T;
    }

    public List<T> List()
    {
        return value as List<T>;
    }
}
public class NameObj : BaseObj
{
    public string Name { get; set; }
}

我将拥有不止一种类型的 BaseObj 类。

所以,我想知道什么更好:

  1. 首先操作 json 来抓取value,然后反序列化它
  2. 修复我如何反序列化BaseReponse<T>以更好地获取value属性内的泛型

我想现在解决方案 1 可以,因为所有的 json 都遵循该模式,但我希望纯反序列化而不是必须进行字符串操作。

在这里回购:https ://github.com/nateous/JSONDeserializeBaseWithGeneric

标签: c#jsonjson.net

解决方案


您的问题是,虽然BaseResponse<T>是类型化的,但底层数据成员public object value是无类型的,因此 Json.NET 不知道如何反序列化它。它在实践中所做的是将反序列化为足以捕获要反序列化的 JSON 的某种类型,通常是某种JToken层次结构。

既然你不想要这个,你应该输入属性,例如:

public abstract class BaseResponseBase
{
    // Allows for non-generic access to the BaseResponse value if needed
    // Use a method rather than a property to prevent accidental serialization.
    public abstract object GetBaseValue();
}

public class BaseResponse<T> : BaseResponseBase
{
    public override object GetBaseValue() { return Value; }

    public T Value { get; set; }
}

由于该值并不总是继承自BaseObj(特别是,当它是一个列表而不是一个对象时)通用约束不再适用。 BaseResponseBase提供对反序列化值的非泛型访问。如果从不需要这种访问,则可以省略基类。

然后反序列化,执行:

var name = JsonConvert.DeserializeObject<BaseResponse<NameObj>>("{ value: {...} }").Value;

var nameList = JsonConvert.DeserializeObject<BaseResponse<List<NameObj>>>("{ value: [{...}] }").Value;

顺便说一句,您总是可以只使用JsonConvert.DeserializeAnonymousType来剥离外部容器对象:

var name = JsonConvert.DeserializeAnonymousType("{ value: {...} }", 
                                                new { value = (NameObj)null })
    .value;

这比使用字符串操作反序列化 JSON 更可取。


推荐阅读