接口的反序列化数组

本文关键字:数组 反序列化 接口 | 更新日期: 2023-09-27 18:12:33

在json。net中出现"type is interface, cannot be instantiated "反序列化错误尽管我在对象上指定了类型我试图反序列化

private static JsonSerializerSettings settings = new JsonSerializerSettings { 
    TypeNameHandling = TypeNameHandling.Auto };
/// <summary>
/// Returns an object created from the jObject and placed in a stub object
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="jObj"></param>
/// <returns></returns>
public static T FromJObject<T>(JToken jObj)
{
    if (jObj == null)
    {
        jObj = new JObject();
    }
    if (jObj is JValue)
    {
        return (T)((JValue)jObj).Value;
    }
    else
    {
        return (T)JsonConvert.DeserializeObject<T>(jObj.ToString(), settings);
    }
 }

this is jObj

{
  "Id": 2,
  "Name": "Name",
  "JsonMapEnum": 0,
  "Validations": [
    {
      "Id": 1,
      "$type": "JsonMap.Default.JValidation, JsonMap"
    }
  ],
  "JSType": 3,
  "SubJsonMapEnum": -1,
  "$type": "JsonMap.Default.JAttribute, JsonMap"
}

错误

Could not create an instance of type JsonMap.Interfaces.IValidation. Type is an interface or abstract class and cannot be instantated. Path 'Validations[0].Id'

看起来它试图把Id变成一个验证对象。为什么?

这些是由我的类型

实现的接口
public interface IJsonMap
{
    long Id { get; set; }
    String Name { get; set; }
    LazyEnum JsonMapEnum { get; set; }
}
public interface IAttribute : IJsonMap
{
    IEnumerable<IValidation> Validations { get; set; }
    LazyEnum JSType { get; set; }
    LazyEnum SubJsonMapEnum { get; set; }
}
public interface IValidation : IJsonMap
{
    IEnumerable<IArgument> Arguments { get; set; }
}

这是呼叫

FromJObject<JAttribute>(CreationJObj)

JAttribute实现IAttribute

接口的反序列化数组

显然,"$type"必须是String字面值中的第一个属性,以便类型名称处理程序捕获该类型。我想这是因为反序列化器没有检查$type是否存在,它只是使用json字符串阅读器,在找到第一个没有设置类型的属性时,它就失败了。

下面是我创建的确保$type总是优先

的方法
    private static JToken ReorderJToken(this JToken jTok)
    {
        if (jTok is JArray)
        {
            var jArr = new JArray();
            foreach (var token in jTok as JArray)
            {
                jArr.Add(token.ReorderJToken());
            }
            return jArr;
        }
        else if( jTok is JObject)
        {
            var jObj = new JObject();
            foreach(var prop in (jTok as JObject).Properties().OrderBy(x=> x.Name))
            {
                prop.Value = prop.Value.ReorderJToken();
                jObj.Add(prop);
            }
            return jObj;
        }
        return jTok;
    }

显然,它不能根据您提供给它的参数推断出正确的类型。如果没有更多关于它如何命名的背景,我就无法让你的东西奏效。但是,如果您使用转换为接口类型的对象调用它,则它将不起作用。根据定义,FromObject必须总是被调用T是类的类型。首先要做的是确保永远不要尝试调用T等于typeof(IOneOfMyInterfaces)的方法,因为这肯定会失败。如果这不能解决问题,我将尝试调用不同版本的反序列化方法;

IMyInterface obj = (IMyInterface)serializer.Deserialize(validatingReader, t);

这适用于validatingReader是JsonReader, t是实现IMyInterface的类对象的Type。我目前使用它与json模式的通用反序列化验证json的正确性。