2017-09-05 175 views
0

我需要为现有报告界面实现远程连接,这需要序列化和反序列化数据类。这里是类和接口的简化版本:JSON Newtonsoft C#反序列化不同类型的对象列表

public interface IBase 
    { 
     string Name { get; } 
    } 

    public interface IDerived1 
    { 
     int Value { get; } 
    } 

    public interface IDerived2 
    { 
     bool Value { get; } 
    } 

    public class Base : IBase 
    { 
     public string Name { get; protected set; } 
    } 

    public class Derived1 : Base, IDerived1 
    { 
     public int Value { get; protected set; } 
    } 

    public class Derived2 : Base, IDerived2 
    { 
     public bool Value { get; protected set; } 
    } 

作为输入参数,我得到

IEnumerable<IBase> reportingData 

所以这个集合可能包含“Derived1”和“Derived2的”实例的任何数量和组合。然后我连载这样的集合:

string serialisedReportingData = JsonConvert.SerializeObject(reportingData); 

这使我如此:

[{ “值”:11, “姓名”: “产品编号”},{ “值”:假的,“Name”:“Output 1 Enabled”}]

很显然,单独使用这些数据,反序列化是不可能的,因为单个集合条目的类型不在JSON中。例如,我可以将类型部分作为JSON的一部分,或者提供额外的类型集合以便在反序列化过程中使用。

我用CustomCreationConverter过载前应对

JsonConvert.DeserializeObject<IEnumerable<Ixxx>>(...); 

类型的场景,但这仅适用于IEnumerable的内一个单一的接口类型。在我上面的例子中,我有两个:IDerived1和IDerived2。

我的问题/问题:

一)我不知道如何CustomCreationConverter可以写,与一个以上的接口类型交易和我不知道怎么弄的类型到这个。

b)我很乐意提供关于如何实现解决方案的建议,该解决方案可以为我提供与收到的'IEnumerable reportingData'相同的反序列化输出。

如果可能,我会非常感谢一个有效的代码示例。

提前许多感谢, 基督教

+0

如果你不想包含'“$型”'信息,请参见如何实现自定义JsonConverter在JSON.NET反序列化基类对象的列表?(https://开头计算器。com/q/8030538)和[使用json.net反序列化多态json类而没有类型信息](https://stackoverflow.com/q/19307752)。 – dbc

回答

1

更新:(由DBC评论启发)

与类型名反序列化时,应使用一个SerializationBinder。 请参阅KnownTypesBinder。 (需要Newtonsoft.Json版本大于10)

首先,如果你想设置你的属性,你必须让它们为public。 然后,您可以使用JsonSerializerSettings来序列化/反序列化。

List<IBase> loList = new List<IBase>(); 
loList.Add(new Base() { Name = "Base" }); 
loList.Add(new Derived1() { Name = "Derived1", Value = 3 }); 
loList.Add(new Derived2() { Name = "Derived2", Value = true }); 

KnownTypesBinder loKnownTypesBinder = new KnownTypesBinder() 
{ 
    KnownTypes = new List<Type> { typeof(Base), typeof(Derived1), typeof(Derived2) } 
}; 

IEnumerable<IBase> reportingData = loList.AsEnumerable(); 
JsonSerializerSettings loJsonSerializerSettings = new JsonSerializerSettings() 
{ 
    TypeNameHandling = TypeNameHandling.Objects, 
    SerializationBinder = loKnownTypesBinder 
}; 

string lsOut = JsonConvert.SerializeObject(reportingData, loJsonSerializerSettings); 
reportingData = JsonConvert.DeserializeObject<IEnumerable<IBase>>(lsOut, loJsonSerializerSettings); 

如果使用类似JsonSerializerSettings的类型信息将被包含在json字符串中。

[{ 
     "$type": "Base", 
     "Name": "Base" 
    }, { 
     "$type": "Derived1", 
     "Value": 3, 
     "Name": "Derived1" 
    }, { 
     "$type": "Derived2", 
     "Value": true, 
     "Name": "Derived2" 
    } 
] 
+0

为了安全起见,应对$ type信息进行消毒。有关详细信息,请参见[Newtonsoft Json中的[TypeNameHandling注意事项](https://stackoverflow.com/q/39565954)。 – dbc

+0

@dbc:Thx。我已经更新了我的答案。 – PinBack

+0

谢谢SOOOO!我没有想到答案是那么简单。不仅我,而且我的一些同事会非常感谢你的智慧! :-) – Christian

相关问题