我正在研究一种协议,其中接收器将接收某些指定自定义类型的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);
并且它将返回三种消息类型之一OR null - 如果存在解析错误/ json与任何预定义类型都不匹配。
更新:我可以控制发送方/接收方以及协议设计。
答案 0 :(得分:4)
如果消息可以指定其类型,将会很有帮助。否则你必须从某个财产或其他财产推断它。
序列化时可以使用消息包装类,如下所示:
public class MessageWrapper<T>
{
public string MessageType { get { return typeof(T).FullName; } }
public T Message { get; set; }
}
因此,如果您的班级Name
具有First
和Last
属性,则可以将其序列化为:
var nameMessage = new MessageWrapper<Name>();
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<MessageWrapper>(serialized);
从MessageType
属性中提取消息类型。
var messageType = Type.GetType(deserialized.MessageType);
现在您知道了类型,您可以反序列化Message
属性。
var message = JsonConvert.DeserializeObject(
Convert.ToString(deserialized.Message), messageType);
message
是object
,但您可以将其转换为Name
或其实际所在的类别。
答案 1 :(得分:1)
function htmlEntities(str) {
return String(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
}
Json 示例:
var log = JsonConvert.DeserializeObject<Log>(File.ReadAllText("log.example.json");
public class Log
{
[JsonConverter(typeof(MessageConverter))]
public object[] Messages { get; set; }
}
public class MessageA
{
public string Message;
}
public class MessageB
{
public int value;
}
public class MessageC
{
public string ValueA;
public string ValueB;
}
public class MessageConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return true;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
object ReadMessage(JObject jobject)
{
if (jobject.Property("Message") != null)
return jobject.ToObject<MessageA>(serializer);
if (jobject.Property("value") != null)
return jobject.ToObject<MessageB>(serializer);
if (jobject.Property("ValueA") != null)
return jobject.ToObject<MessageC>(serializer);
throw new Exception("Type is not recognized");
}
var jarray = JArray.Load(reader);
return jarray.Select(jitem => ReadMessage((JObject)jitem)).ToArray();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
答案 2 :(得分:0)
希望您熟悉工厂模式,您可以使用工厂并在json中包含“Type”属性,让我们称之为_t
。
您可以自己解析json字符串并找到_t
属性的值,将其反序列化为dynamic
并获取jsonObj._t
或只有一个简单的class
_t
字段仅用于最初将json反序列化。
然后,您可以将表示C#类型的string
传递给工厂,并为Type
获取json反序列化器。
然后,您可以分别添加和处理所有传出和传入呼叫,以便将来很容易添加新类型,只需添加和注册您需要的序列化程序/解串器_t
与工厂合作。