0

I want to deserialize a JSON message received from TCP/IP in my C# application. I have really simple classes with one or two Properties at most, but they are derived. For example:

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;
    }
}

I made a few attempts with DataMember and DataContract attributes to solve my problem, but it didn't fix it.

The problem lies here:

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;
     }
}

If i want to deserialize with a proper format, containing all the necessary properties, it works:

This works: {"Response":"SomeResponse","Info":"Information","UID":"123"}

However, this also works: {"nonexistingProperty":"value"}

The second one also creates a RequestCommand with property values set to null.

1st question: How can I force my messagetranslator function to make RequestCommand only if it receives all of the required properties

2nd question: If i have multiple command types which are derived from one or more ancestors, how is it possible, to deserialize it automatically from the "deepest" class if the received properties allow it.

EDIT:

I serialize/deserialize with these two

    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);
    }

The break in the try catch supposed to end the loop if the TrySerialize doesn't throw an exception, therefore the deserialization was successful.

SLOBY
  • 1,007
  • 2
  • 10
  • 24
  • How are you are Serializing and De-Serializing objects? And why there is break after call to `TryDeserialize` function. – Amar Palsapure Jan 20 '12 at 08:33
  • Have a look at http://stackoverflow.com/questions/1100191/javascriptserializer-deserialize-how-to-change-field-names. In `TryDeserialize` you don't require `Type`, you can `typeof(RequestCommand)`. Also provide complete code, `RequestCommand`, `StartProcessesRequestCommand`, `ClientProcess` class is missing. – Amar Palsapure Jan 20 '12 at 10:03

1 Answers1

0

If you actually used DataContractJsonSerializer, and you decorated the members / types in question with DataMember / DataContract, you can actually get this to happen. To do this, you can decorate ALL data members with [IsRequired=true]. This would throw an exception if the members weren't present on the wire.

Another option you have is to use IObjectReference, which let you translate one object to another post-serialization, and you can do this depending on what is deserialized from the wire.

krisragh MSFT
  • 1,908
  • 1
  • 13
  • 22