2

即使我在我试图反序列化的对象上指定类型,我也收到 json.net 的“类型是接口,无法实例化”反序列化错误

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

这是乔布斯

{
  "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 转换为 Validation 对象。为什么?

这些是我的类型实现的接口

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

4

2 回答 2

2

显然,“$type”必须是字符串文字中的第一个属性,以便类型名称处理程序可以捕获该类型。我想这是因为反序列化器没有检查 $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;
    }
于 2013-05-07T18:25:58.967 回答
0

很明显,它无法根据您提供的参数推断出正确的类型。如果没有更多关于它的名称的上下文,我无法让你拥有的东西起作用。但是,如果您使用转换为接口类型的对象调用它,它将不起作用。FromObject必须始终使用类的类型来调用您的定义T。首先要做的是确保你永远不要尝试调用T等于的方法,typeof(IOneOfMyInterfaces)因为这肯定会失败。如果那不能解决它,我会尝试调用不同版本的反序列化方法;

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

这适用于 validatingReader 是 aJsonReader并且tType实现 的类对象的情况IMyInterface。我目前正在使用它进行通用反序列化,使用 json 模式来验证 json 的正确性。

于 2013-05-07T16:31:52.043 回答