/// <summary>
        /// Init constructor.
        /// </summary>
        public SubscribeRequest(string clientID, string subscriptionChannel, IJSonWritable data, IJSonWritable ext)
            : base(MetaChannel, data, ext)
        {
            if (!BayeuxChannel.IsValid(subscriptionChannel))
            {
                throw new ArgumentException("SubscriptionChannel failed a standard validation", "subscriptionChannel");
            }

            ClientID            = clientID;
            SubscriptionChannel = subscriptionChannel;
        }
        /// <summary>
        /// Init constructor.
        /// </summary>
        public PublishRequest(string clientID, string channel, IJSonWritable eventData, IJSonWritable data, IJSonWritable ext)
            : base(channel, data, ext)
        {
            if (!BayeuxChannel.IsValid(channel))
            {
                throw new ArgumentException("Channel failed a standard validation", "channel");
            }

            ClientID  = clientID;
            EventData = eventData;
        }
        /// <summary>
        /// Reads the response from given JSON object.
        /// </summary>
        public void Read(IJSonObject input)
        {
            _jsonResponse = input;

            // reset all fields to their default values:
            Channel    = null;
            ClientID   = null;
            Successful = false;
            Timestamp  = DateTime.MinValue;
            ID         = null;
            Data       = null;
            Error      = null;
            Advice     = null;
            Ext        = null;

            // stop processing, if there is no input data given:
            if (input == null)
            {
                return;
            }

            // now read the Bayeux mandatory fields:
            Channel = input["channel"].StringValue;
            if (!BayeuxChannel.IsValid(Channel))
            {
                throw new FormatException("Invalid channel format");
            }


            if (input.Contains("clientId"))
            {
                ClientID = input["clientId"].StringValue;
            }

            // for meta channels, this field is required,
            // however it's optional for others (like events)
            if (Channel.StartsWith("/meta"))
            {
                Successful = input["successful"].BooleanValue;
            }
            else
            {
                if (input.Contains("successful"))
                {
                    Successful = input["successful"].BooleanValue;
                }
            }

            // parse optional fields:
            if (input.Contains("timestamp"))
            {
                Timestamp = input["timestamp"].DateTimeValue;
            }
            if (input.Contains("id"))
            {
                ID = input["id"].StringValue;
            }
            if (input.Contains("data"))
            {
                Data = input["data"];
            }
            if (input.Contains("error"))
            {
                Error = new BayeuxError(input["error"].StringValue);
            }
            if (input.Contains("advice"))
            {
                Advice = new BayeuxAdvice(input["advice"]);
            }
            if (input.Contains("ext"))
            {
                Ext = input["ext"];
            }

            ReadOptionalFields(input);
        }