问题 使用newtonsoft.json反序列化List


我正在尝试序列化和反序列化列表 abstract 课程(mustinherit 对于vb),在它内部显然只有派生类的实例。

我用list装饰了list参数 JsonProperty(ItemTypeNameHandling = TypeNameHandling.Auto) 获得如下所示的输出:

但是当我反序列化时,它一直说他不能反序列化抽象类。

http://james.newtonking.com/json/help/index.html?topic=html/SerializeTypeNameHandling.htm

public class ConcreteClass
{
    private ObservableCollection<AbstractClass> _Nodes = new ObservableCollection<AbstractClass>();
    //<Newtonsoft.Json.JsonProperty(itemtypenamehandling:=Newtonsoft.Json.TypeNameHandling.Auto)>
    public ObservableCollection<AbstractClass> Nodes {
        get { return this._Nodes; }
    }
    public string Name { get; set; }
    public int Id { get; set; }
}

public abstract class AbstractClass
{
    private ObservableCollection<AbstractClass> _Nodes = new ObservableCollection<AbstractClass>();
    [Newtonsoft.Json.JsonProperty(itemtypenamehandling = Newtonsoft.Json.TypeNameHandling.Auto)]
    public ObservableCollection<AbstractClass> Nodes {
        get { return this._Nodes; }
    }
}

删除它起作用的注释行!


4185
2017-11-18 01:10


起源

请发布您的反序列化代码。 - Timothy Walters
另外,请发布您的课程。 - Brian Rogers
我一到办公室就会更新问题 - L.Trabacchin


答案:


根据文档,确保在反序列化时指定TypeNameHandling:

// for security TypeNameHandling is required when deserializing
Stockholder newStockholder = JsonConvert.DeserializeObject<Stockholder>(jsonTypeNameAuto, new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Auto
});

值得注意的是,文档正在反序列化一个Concrete类 包含 抽象类的集合。

作为一个实验尝试创建一个抛弃类(具体),它具有一个带有抽象对象列表的单个属性,并查看是否可以序列化和反序列化它。

更新:

我刚在LINQPad中测试了以下代码:

void Main()
{
    var test = new List<Business>();
    test.Add(new Hotel { Name = "Hilton", Stars = 5 });
    test.Add(new Pool { Name = "Big Splash", Capacity = 500 });

    test.Dump();

    string json = JsonConvert.SerializeObject(test, Newtonsoft.Json.Formatting.Indented, new JsonSerializerSettings
    {
        TypeNameHandling = TypeNameHandling.All
    });

    json.Dump();

    var businesses = JsonConvert.DeserializeObject<List<Business>>(json, new JsonSerializerSettings
    {
        TypeNameHandling = TypeNameHandling.All
    });

    businesses.Dump();
}

// Define other methods and classes here
public abstract class Business
{
    public string Name { get;set; }
}
public class Hotel : Business
{
    public int Stars { get;set; }
}
public class Pool : Business
{
    public int Capacity { get;set;}
}

它工作得很好。抽象集合序列化为:

{
  "$type": "System.Collections.Generic.List`1[[UserQuery+Business, query_jvrdcu]], mscorlib",
  "$values": [
    {
      "$type": "UserQuery+Hotel, query_jvrdcu",
      "Stars": 5,
      "Name": "Hilton"
    },
    {
      "$type": "UserQuery+Pool, query_jvrdcu",
      "Capacity": 500,
      "Name": "Big Splash"
    }
  ]
}

原始和反序列化的集合匹配。


16
2017-11-18 02:55



实际上就是这样,但是,抽象类中还有一个列表,因为它是一个树节点结构。 - L.Trabacchin
我还尝试在反序列化中指定选项 - L.Trabacchin
@ L.Trabacchin我发布了工作示例代码(如果您在“C#Program”模式下使用LINQPad并参考Newtonsoft.Json)。 - Timothy Walters
如果您编辑它以使用装饰器而不是设置我将接受您的答案 - L.Trabacchin