将json反序列化为具有通用类型的基础对象

时间:2018-09-21 21:24:46

标签: c# json json.net

我有一个c#类,可让您指定泛型类型。我希望能够重用该类来消除所有对象将共享的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

2 个答案:

答案 0 :(得分:1)

您的问题是,在键入$ vars="-n" $ printf '%s\n' "$vars" -n 的同时,底层数据成员BaseResponse<T>的类型也没有,因此Json.NET不知道如何反序列化它。实际上,它要做的是将反序列化为某种类型,该类型足以捕获要反序列化的JSON,通常是某些JToken层次结构。

由于您不需要这样做,因此应输入属性,例如像这样:

public object value

由于值并不总是从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

偶然地,您始终可以使用JsonConvert.DeserializeAnonymousType来剥离外部容器对象:

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

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

这比使用字符串操作反序列化JSON更为严格。

答案 1 :(得分:1)

要解决此问题:

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

将BaseResponse类中的值类型从object更改为T。

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

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

    public List<T> List()
    {
        return value as List<T>;
    }
}

现在,此:

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

反序列化ListBaseJSON返回BaseObj数组,但是BaseResponse类具有BaseObj约束。您可能必须删除约束。

因此您的BaseResponse类变为:

public class BaseResponse<T>
{
    public T value;

    public T Get()
    {
        return value;
    }

}

因此,现在您可以:

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