private static Session DeserializeAsSession(global::ServiceStack.Text.JsonObject jsonObject)
        {
            var session = CreateEnvelope <Session>(jsonObject);

            session.Mode               = jsonObject.Get <SessionMode>(Session.MODE_KEY);
            session.State              = jsonObject.Get <SessionState>(Session.STATE_KEY);
            session.Reason             = jsonObject.Get <Reason>(Session.REASON_KEY);
            session.Encryption         = jsonObject.Get <SessionEncryption?>(Session.ENCRYPTION_KEY);
            session.EncryptionOptions  = jsonObject.Get <SessionEncryption[]>(Session.ENCRYPTION_OPTIONS_KEY);
            session.Compression        = jsonObject.Get <SessionCompression?>(Session.COMPRESSION_KEY);
            session.CompressionOptions = jsonObject.Get <SessionCompression[]>(Session.COMPRESSION_OPTIONS_KEY);
            session.SchemeOptions      = jsonObject.Get <AuthenticationScheme[]>(Session.SCHEME_OPTIONS_KEY);

            if (jsonObject.ContainsKey(Session.SCHEME_KEY))
            {
                AuthenticationScheme scheme;
                if (!Enum.TryParse <AuthenticationScheme>(jsonObject[Session.SCHEME_KEY], true, out scheme))
                {
                    throw new ArgumentException("Invalid or unknown authentication scheme name");
                }

                Type authenticationType;
                if (!TypeUtil.TryGetTypeForAuthenticationScheme(scheme, out authenticationType))
                {
                    throw new ArgumentException("Unknown authentication mechanism");
                }

                if (jsonObject.ContainsKey(Session.AUTHENTICATION_KEY))
                {
                    session.Authentication = (Authentication)global::ServiceStack.Text.JsonSerializer.DeserializeFromString(
                        jsonObject.GetUnescaped(Session.AUTHENTICATION_KEY), authenticationType);
                }
                else
                {
                    session.Authentication = (Authentication)TypeUtil.CreateInstance(authenticationType);
                }
            }

            return(session);
        }
        private static Document GetDocument(global::ServiceStack.Text.JsonObject jsonObject, string typeKey, string documentPropertyName)
        {
            Document document = null;

            if (jsonObject.ContainsKey(typeKey))
            {
                var  mediaType = jsonObject.Get <MediaType>(typeKey);
                Type documentType;

                if (mediaType.IsJson)
                {
                    if (TypeUtil.TryGetTypeForMediaType(mediaType, out documentType))
                    {
                        if (jsonObject.ContainsKey(documentPropertyName))
                        {
                            var documentString = jsonObject.GetUnescaped(documentPropertyName);

                            document = (Document)global::ServiceStack.Text.JsonSerializer.DeserializeFromString(
                                documentString, documentType);
                        }
                        else
                        {
                            document = (Document)TypeUtil.CreateInstance(documentType);
                        }
                    }
                    else
                    {
                        if (jsonObject.ContainsKey(documentPropertyName))
                        {
                            var documentJsonObject = jsonObject.Get <global::ServiceStack.Text.JsonObject>(documentPropertyName);
                            var documentDictionary = documentJsonObject
                                                     .ToDictionary(k => k.Key, v => (object)v.Value);

                            document = new JsonDocument(documentDictionary, mediaType);
                        }
                        else
                        {
                            document = new JsonDocument(mediaType);
                        }
                    }
                }
                else
                {
                    string documentString = null;

                    if (jsonObject.ContainsKey(documentPropertyName))
                    {
                        documentString = jsonObject.GetUnescaped(documentPropertyName);
                    }

                    if (TypeUtil.TryGetTypeForMediaType(mediaType, out documentType))
                    {
                        if (!string.IsNullOrWhiteSpace(documentString))
                        {
                            var parseFunc = TypeUtil.GetParseFuncForType(documentType);
                            document = (Document)parseFunc(documentString);
                        }
                        else
                        {
                            document = (Document)TypeUtil.CreateInstance(documentType);
                        }
                    }
                    else
                    {
                        document = new PlainDocument(documentString, mediaType);
                    }
                }
            }

            return(document);
        }