c# - Json.net反序列化数组接口(interface)

标签 c# json interface polymorphism json.net

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

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

这是jObj

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

这是错误

无法创建 JsonMap.Interfaces.IValidation 类型的实例。类型是接口(interface)或抽象类,不能实例化。路径“验证[0].Id”

看起来它正在尝试将 Id 转换为 Validation 对象。为什么?

这些是我的类型实现的接口(interface)

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”必须是字符串文字中的第一个属性,以便类型名称处理程序捕获该类型。我想这是因为反序列化器不检查 $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;
    }

关于c# - Json.net反序列化数组接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16423795/

相关文章:

interface - 我应该用 Duck Typed 语言定义接口(interface)吗?

c# - 确保封装的自定义属性

c# - 允许用户通过拖动调整 WPF TreeView 节点的大小

C# Graphics.DrawString RectangleF 自动高度 : How to find that height?

php - PHP 中的 MySQL 查询

ios - Swift 的通用 JSON 解析器

java - 如何使用Extjs进行ajax调用以从jsp中的数据库获取数据?

java - JAVA中将接口(interface)定义为变量类型

c# - Xamarin 表单 + Prism 登录流程

与服务器交互的 Android 应用程序