我想在C#应用程序中反序列化从TCP/IP接收的JSON消息。我有一些非常简单的类,最多有一两个属性,但它们是派生的。例如:
public class SemiCommand
{
public SemiCommand()
{
UID = string.Empty;
}
public SemiCommand(string uid)
{
UID = uid;
}
public string UID
{
get;
set;
}
public new string ToString()
{
return new JavaScriptSerializer().Serialize(this);
}
}
public class ResponseCommand : SemiCommand
{
protected const string DEFAULT_INFO = "OK";
public ResponseCommand()
{
UID = string.Empty;
Info = DEFAULT_INFO;
}
public ResponseCommand(string uid)
{
UID = uid;
Info = DEFAULT_INFO;
}
public string Response
{
get;
set;
}
public string Info
{
get;
set;
}
public class GetInfoResponseCommand : ResponseCommand
{
public GetInfoResponseCommand()
: base()
{
Response = "GetInfoResponse";
}
public List<ClientProcess> Processes
{
get;
set;
}
}
我尝试使用DataMember和DataContract属性来解决我的问题,但没有解决
问题就在这里:
private Type[] _deserializationTypes = new Type[] { typeof(StartProcessesRequestCommand), typeof(RequestCommand) };
public RequestCommand TranslateTCPMessageToCommand(string messageInString)
{
RequestCommand requestCommand = null;
for (int i = 0; i < _deserializationTypes.Length; i++)
{
try
{
requestCommand = TryDeserialize(_deserializationTypes[i], messageInString);
break;
}
catch
{
}
}
if (requestCommand == null || (requestCommand != null && requestCommand.Command == string.Empty))
{
throw new System.Runtime.Serialization.SerializationException("Unable to deserialize received message");
}
else
{
return requestCommand;
}
}
如果我想使用包含所有必要属性的正确格式进行反序列化,它是有效的:
这项工作:{"Response":"SomeResponse","Info":"Information","UID":"123"}
然而,这也起作用:{"nonexistingProperty":"value"}
第二个还创建了一个属性值设置为null的RequestCommand。
第一个问题:只有当我的messagetranslator函数接收到所有必需的属性时,我才能强制它使RequestCommand
第二个问题:如果我有多个从一个或多个祖先派生的命令类型,如果接收到的属性允许,如何从"最深"类自动反序列化它?
编辑:
我用这两个进行序列化/反序列化
private RequestCommand TryDeserialize(Type type, string messageInString)
{
JavaScriptSerializer js = new JavaScriptSerializer();
return (RequestCommand)js.Deserialize(messageInString, type);
}
public string TranslateCommandToTCPMessage(ResponseCommand command)
{
JavaScriptSerializer js = new JavaScriptSerializer();
return js.Serialize(command);
}
如果TrySerialize没有抛出异常,则try-catch中的中断应该结束循环,因此反序列化成功。
如果您实际使用了DataContractJsonSerializer,并且使用DataMember/DataContract修饰了有问题的成员/类型,那么您实际上可以实现这一点。为此,您可以用[IsRequired=true]修饰所有数据成员。如果成员不在场,这将引发异常。
您的另一个选择是使用IObjectReference,它允许您在序列化后将一个对象转换为另一个对象,并且您可以根据从连线反序列化的内容来执行此操作。