在json反序列化期间确定类型
我正在研究一种协议,其中接收器将接收某些指定自定义类型的json消息(当前为5,但可能为10-20)。 我正在努力想出一个最优/快速的解决方案,它将自动反序列化json并返回正确类型的对象。
例:
public class MessageA { public string Message; } public class MessageB { public int value; } public class MessageC { public string ValueA; public string ValueB; }
理想情况下,该方法应该是这样的
Object Deserialize(string json);
并且它将返回三种消息类型之一或null – 如果存在解析错误/ json与任何预定义类型都不匹配。
更新:我可以控制发送器/接收器以及协议设计。
如果消息可以指定其类型,将会很有帮助。 否则你必须从某个财产或其他财产推断它。
您可以在序列化时使用消息包装类,如下所示:
public class MessageWrapper { public string MessageType { get { return typeof(T).FullName; } } public T Message { get; set; } }
因此,如果您有一个具有First
和Last
属性的类Name
,您可以像这样序列化它:
var nameMessage = new MessageWrapper(); nameMessage.Message = new Name {First="Bob", Last = "Smith"}; var serialized = JsonConvert.SerializeObject(nameMessage);
序列化的JSON是
{"MessageType":"YourAssembly.Name","Message":{"First":"Bob","Last":"Smith"}}
反序列化时,首先将JSON反序列化为此类型:
public class MessageWrapper { public string MessageType { get; set; } public object Message { get; set; } } var deserialized = JsonConvert.DeserializeObject(serialized);
从MessageType
属性中提取消息类型。
var messageType = Type.GetType(deserialized.MessageType);
既然知道了类型,就可以反序列化Message
属性。
var message = JsonConvert.DeserializeObject( Convert.ToString(deserialized.Message), messageType);
message
是一个object
,但您可以将其强制转换为Name
或其实际所在的类。
希望您熟悉工厂模式,您可以使用工厂并将“Type”属性作为json的一部分包含在内,让我们称之为_t
。
您可以自己解析json字符串并找到_t
属性的值,将其反序列化为dynamic
并获取jsonObj._t
或者只有一个只有_t
字段的简单class
,以便最初将json反序列化。
然后,您可以将表示C#Type的string
传递给工厂,并为该Type
获取json反序列化器。
然后,您可以分别对所有传出和传入呼叫添加和处理_t
参数,以便将来很容易添加新类型,只需添加并注册该Type
与工厂所需的序列化器/反序列化器。