将JSON反序列化为具有泛型类型参数的接口列表



如标题所述,我正试图反序列化JSON,但我遇到了一些麻烦。我认为下面包含了必要的信息。

public class Variable<T> : IVariable where T : IConvertible
{
//...
}
public class ArrayVariable<T> : IVariable where T : IConvertible
{
//...
}

所以我有一个IVariable列表,然后我成功序列化(所有信息都在json中):

JsonConvert.SerializeObject(myIVariableList)

现在我正试图对它进行反序列化,但我很难确定正确的方法,因为除了VariableArrayVariable类型之外,它还涉及找到通用类型T。我已经试过了

JsonConvert.DeserializeObject<List<IVariable>>(result.newValues)

,但显然,您可以创建接口的实例。如有任何帮助,不胜感激。

您可以使用TypeNameHandling.All,但我强烈建议您避免使用它,因为它非常危险,并且允许攻击者破坏您的代码。

另一个更安全的选择是使用自定义转换器。下面是一个非常简单(和脆弱)的示例,可以帮助您入门:

首先让我们创建一些共享接口的基本类:

public interface IVariable { }
public class Foo : IVariable
{
public int A { get; set; }
}
public class Bar : IVariable
{
public int B { get; set; }
}

现在我们可以制作我们的转换器:

public class IVariableConverter : JsonConverter<IVariable>
{
public override IVariable ReadJson(JsonReader reader, Type objectType, 
IVariable existingValue, bool hasExistingValue, JsonSerializer serializer)
{
// First load the JSON into a JObject
var variable = JObject.Load(reader);
// If the JSON had a property called A, it must be a Foo:
if (variable.ContainsKey("A"))
{
return variable.ToObject<Foo>();
}
// If the JSON had a property called B, it must be a Bar:
if (variable.ContainsKey("B"))
{
return variable.ToObject<Bar>();
}
// And who knows what was passed in if it was missing both of those properties?!
throw new Exception("Er, no idea what that JSON was supposed to be!");

}
public override void WriteJson(JsonWriter writer, IVariable value, 
JsonSerializer serializer)
{
// Feel free to write your own code here if you need it
throw new NotImplementedException();
}
}

现在我们可以做一些实际的反序列化:

// A basic JSON example:
var json = "[{"A":1},{"B":2}]";
// The settings to tell the serialiser how to process an IVariable object
var settings = new JsonSerializerSettings
{
Converters = new List<JsonConverter> { new IVariableConverter() }
};
// And deserialise with the defined settings
var result = JsonConvert.DeserializeObject<List<IVariable>>(json, settings);

你需要在如何识别每种类型上更有创造性,但这是实现你需要的安全方法。

您可以使用TypeNameHandling.All将类型信息添加到序列化的json中,然后在解析过程中使用它:

var variables = new List<IVariable>()
{
new Variable<int>()
};
var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };
var serializeObject = JsonConvert.SerializeObject(variables, settings);
var list = JsonConvert.DeserializeObject<List<IVariable>>(serializeObject, settings);

相关内容

  • 没有找到相关文章

最新更新