예제 #1
0
        public Task <string> SerializeSchema(Type t, HttpDataSerializerOptions options = null)
        {
            options = options ?? new HttpDataSerializerOptions();
            var schema = GetSchema(t, options, useStringEnums: false, requireReferenceTypes: false);

            return(Task.FromResult(schema.ToJson(Formatting.Indented)));
        }
예제 #2
0
        public static JsonSerializerOptions CreateJsonSerializerOptions(HttpDataSerializerOptions options, bool debugMode)
        {
            options = options ?? new HttpDataSerializerOptions();
            var opts = new JsonSerializerOptions
            {
                WriteIndented               = debugMode,
                DictionaryKeyPolicy         = JsonNamingPolicy.CamelCase,
                PropertyNamingPolicy        = JsonNamingPolicy.CamelCase,
                DefaultIgnoreCondition      = JsonIgnoreCondition.WhenWritingNull,
                PropertyNameCaseInsensitive = true
            };

            opts.Converters.Add(new JsonTokenConverterFactory());

            if (options.EnumSerializationMethod == EnumSerializationMethod.Object)
            {
                opts.Converters.Add(new JsonEnumConverterFactory());
            }
            if (options.EnumSerializationMethod == EnumSerializationMethod.String)
            {
                opts.Converters.Add(new JsonStringEnumConverter());
            }

            return(opts);
        }
예제 #3
0
        public async Task <T> DeserializeResponse <T>(byte[] message, HttpDataSerializerOptions options = null) where T : new()
        {
            await Task.CompletedTask;
            var settings = JsonNetSerializerSettings.CreateJsonSerializerSettings(options, _debugMode);

            if (message.Length == 0)
            {
                throw new CodeWorksSerializationException("Cannot deserialize an empty payload");
            }

            try
            {
                using (var ms = new MemoryStream(message))
                {
                    using (var reader = new StreamReader(ms, Encoding.UTF8))
                    {
                        var result = JsonSerializer.Create(settings).Deserialize(reader, typeof(T));
                        return((T)result);
                    }
                }
            }
            catch (JsonException ex)
            {
                var contents = Encoding.UTF8.GetString(message);

                if (string.IsNullOrWhiteSpace(contents))
                {
                    return(new T());
                }
                _logger.LogError(ex, $"Cannot deserialize request payload {contents}");
                throw new CodeWorksSerializationException($"Cannot parse payload as JSON. Payload={contents}", contents);
            }
        }
예제 #4
0
        public static JsonSerializerSettings CreateJsonSerializerSettings(HttpDataSerializerOptions options, bool debugMode)
        {
            options = options ?? new HttpDataSerializerOptions();

            var settings = new JsonSerializerSettings();

            settings.Formatting        = debugMode ? Formatting.Indented : Formatting.None;
            settings.ContractResolver  = new CamelCasePropertyNamesContractResolver();
            settings.NullValueHandling = NullValueHandling.Ignore;

            settings.Converters.Add(new JsonTokenConverter());

            switch (options.EnumSerializationMethod)
            {
            case EnumSerializationMethod.String:
                settings.Converters.Add(new StringEnumConverter());
                break;

            case EnumSerializationMethod.Numeric:
                // NOTHING NEEDED NUMERIC CONVERSION BY DEFAULT
                break;

            case EnumSerializationMethod.Object:
                settings.Converters.Add(new JsonEnumObjectConverter());
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            return(settings);
        }
예제 #5
0
        public Task <string> SerializeExample(Type t, HttpDataSerializerOptions options = null)
        {
            options = options ?? new HttpDataSerializerOptions();
            var schema = GetSchema(t, options, useStringEnums: true, requireReferenceTypes: true);
            var sample = schema.ToSampleJson();
            var json   = sample.ToString(Formatting.Indented);

            return(Task.FromResult(json));
        }
예제 #6
0
        private bool AllowAdditionalPropertiesForJsonSchemaValidation(HttpDataSerializerOptions options)
        {
            var allowProps = new[]
            {
                JsonValidationStrategy.DefaultAllowAdditionalProperties,
                JsonValidationStrategy.ForceAllowAdditionalProperties
            };

            return(allowProps.Contains(options.JsonSchemaValidation));
        }
예제 #7
0
        private HttpDataSerializerOptions CreateOptionsFromHeaders(HttpRequestHeaders headers)
        {
            var opts = new HttpDataSerializerOptions
            {
                IncludeDependencyMetaData = ParseHeaderForEnum <IncludeDependencyMetaDataStrategy>(headers, "codeworks-prefs-dep-meta"),
                EnumSerializationMethod   = ParseHeaderForEnum <EnumSerializationMethod>(headers, "codeworks-prefs-enum"),
                JsonSchemaValidation      = ParseHeaderForEnum <JsonValidationStrategy>(headers, "codeworks-prefs-schema-check")
            };

            return(opts);
        }
예제 #8
0
        public async Task <T> DeserializeResponse <T>(byte[] message, HttpDataSerializerOptions options = null) where T : new()
        {
            var opts = TextJsonSerializerSettings.CreateJsonSerializerOptions(options, _debugMode);

            try
            {
                using (var ms = new MemoryStream(message))
                {
                    var result = await JsonSerializer.DeserializeAsync <T>(ms, opts);

                    return(result);
                }
            }
            catch (JsonException ex)
            {
                _logger.LogError("Cannot deserialize response", ex);
                throw new CodeWorksSerializationException("Cannot deserialize JSON payload", ex);
            }
        }
예제 #9
0
        public async Task <BaseRequest> DeserializeRequest(
            Type type,
            byte[] message,
            HttpDataSerializerOptions options = null)
        {
            var opts = TextJsonSerializerSettings.CreateJsonSerializerOptions(options, _debugMode);

            if (message.Length == 0)
            {
                return((BaseRequest)Activator.CreateInstance(type));
            }

            try
            {
                using (var ms = new MemoryStream(message))
                {
                    var result = await JsonSerializer.DeserializeAsync(ms, type, opts);

                    return((BaseRequest)result);
                }
            }
            catch (JsonException ex)
            {
                var contents = Encoding.UTF8.GetString(message);

                if (ex.StackTrace.Contains("JsonConverterEnum"))
                {
                    // INVALID ENUM FOUND - TRY AND FIGURE IT OUT
                    var property = ex.Path.Substring(2, ex.Path.Length - 2);
                    throw new ValidationErrorException("Invalid enum value provided", property);
                }

                if (string.IsNullOrWhiteSpace(contents))
                {
                    return((BaseRequest)Activator.CreateInstance(type));
                }
                _logger.LogError(ex, $"Cannot deserialize request payload {contents}");
                throw new CodeWorksSerializationException($"Cannot parse payload as JSON. Payload={contents}", contents);
            }
        }
예제 #10
0
        public JsonSchema GetSchema(Type t, HttpDataSerializerOptions options, bool useStringEnums, bool requireReferenceTypes)
        {
            var        settings = GetSchemaSerializationSettings(useStringEnums);
            JsonSchema schema   = JsonSchema.FromType(t, new JsonSchemaGeneratorSettings
            {
                FlattenInheritanceHierarchy           = true,
                AlwaysAllowAdditionalObjectProperties = AllowAdditionalPropertiesForJsonSchemaValidation(options),
                GenerateEnumMappingDescription        = true,
                DefaultReferenceTypeNullHandling      = requireReferenceTypes ? ReferenceTypeNullHandling.NotNull : ReferenceTypeNullHandling.Null,
                SerializerSettings = settings,
                ReflectionService  = new CustomReflectionService(),
                TypeMappers        = new List <ITypeMapper>
                {
                    new TokenStringTypeMapper(),
                    new TokenDateTypeMapper(),
                    new ClientTokenStringTypeMapper(),
                    new ClientTokenDateTypeMapper()
                }
            });

            return(schema);
        }
예제 #11
0
        private bool ShouldValidateSchema(HttpDataSerializerOptions options)
        {
            if (_environmentResolver.Environment == CodeWorksEnvironment.Production)
            {
                var prodValidationOptions = new[]
                {
                    JsonValidationStrategy.ForceStrict,
                    JsonValidationStrategy.ForceAllowAdditionalProperties,
                };
                return(prodValidationOptions.Contains(options.JsonSchemaValidation));
            }

            var nonProdValidationOptions = new[]
            {
                JsonValidationStrategy.DefaultStrict,
                JsonValidationStrategy.DefaultAllowAdditionalProperties,
                JsonValidationStrategy.ForceStrict,
                JsonValidationStrategy.ForceAllowAdditionalProperties,
            };

            return(nonProdValidationOptions.Contains(options.JsonSchemaValidation));
        }
예제 #12
0
        public async Task <BaseRequest> ConvertRequest(Type type, HttpRequestMessage request)
        {
            HttpDataSerializerOptions options = CreateOptionsFromHeaders(request.Headers);

            byte[] contents = await request.Content.ReadAsByteArrayAsync();

            if (ShouldValidateSchema(options))
            {
                var schemaErrors = await _serializationSchema.ValidateSchema(contents, type, options);

                if (schemaErrors.Any())
                {
                    throw new SchemaValidationException($"Cannot validate payload as type of {type.FullName}", schemaErrors);
                }

                BaseRequest validResult = await _serializer.DeserializeRequest(type, contents, options);

                return(validResult);
            }

            BaseRequest result = await _serializer.DeserializeRequest(type, contents, options);

            return(result);
        }
예제 #13
0
        public async Task <ServiceResponse> DeserializeResponse(Type type, byte[] message, HttpDataSerializerOptions options = null)
        {
            var opts = TextJsonSerializerSettings.CreateJsonSerializerOptions(options, _debugMode);

            try
            {
                using (var ms = new MemoryStream(message))
                {
                    var result = await JsonSerializer.DeserializeAsync(ms, type, opts);

                    return((ServiceResponse)result);
                }
            }
            catch (JsonException ex)
            {
                _logger.LogError("Cannot deserialize request", ex);
                throw;
            }
        }
예제 #14
0
        public async Task <BaseRequest> DeserializeRequest(Type type, byte[] message, HttpDataSerializerOptions options = null)
        {
            await Task.CompletedTask;
            var settings = JsonNetSerializerSettings.CreateJsonSerializerSettings(options, _debugMode);

            if (message.Length == 0)
            {
                return((BaseRequest)Activator.CreateInstance(type));
            }

            try
            {
                using (var ms = new MemoryStream(message))
                {
                    using (var reader = new StreamReader(ms, Encoding.UTF8))
                    {
                        var result = JsonSerializer.Create(settings).Deserialize(reader, type);
                        return((BaseRequest)result);
                    }
                }
            }
            catch (JsonSerializationException ex)
            {
                var contents = Encoding.UTF8.GetString(message);
                if (ex.StackTrace.Contains("StringEnumConverter"))
                {
                    // INVALID ENUM FOUND - TRY AND FIGURE IT OUT
                    var property = ex.Path;
                    throw new ValidationErrorException("Invalid value provided", property);
                }

                throw;
            }
            catch (JsonException ex)
            {
                var t = ex.GetType();

                var contents = Encoding.UTF8.GetString(message);
                //StringEnumConverter

                if (ex.StackTrace.Contains("StringEnumConverter"))
                {
                    // INVALID ENUM FOUND - TRY AND FIGURE IT OUT
                    var property = "";
                    throw new ValidationErrorException("Invalid enum value provided", property);
                }

                if (string.IsNullOrWhiteSpace(contents))
                {
                    return((BaseRequest)Activator.CreateInstance(type));
                }

                _logger.LogError(ex, $"Cannot deserialize request payload {contents}");
                throw new CodeWorksSerializationException($"Cannot parse payload as JSON. Payload={contents}",
                                                          contents);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"Cannot deserialize request payload");
                throw new CodeWorksSerializationException($"Cannot parse payload as JSON");
            }
        }
예제 #15
0
        public async Task <T> DeserializeRequest <T>(byte[] message, HttpDataSerializerOptions options = null) where T : BaseRequest, new()
        {
            var r = await DeserializeRequest(typeof(T), message, options);

            return(r as T);
        }
예제 #16
0
        public Task <string> SerializeResponse(ServiceResponse response, Type responseType, HttpDataSerializerOptions options = null)
        {
            var settings = JsonNetSerializerSettings.CreateJsonSerializerSettings(options, _debugMode);
            var res      = JsonConvert.SerializeObject(response, settings);

            return(Task.FromResult(res));
        }
예제 #17
0
        public async Task <string> SerializeRequest(BaseRequest request, Type requestType, HttpDataSerializerOptions options = null)
        {
            var opts = TextJsonSerializerSettings.CreateJsonSerializerOptions(options, _debugMode);

            using (var stream = new MemoryStream())
            {
                await JsonSerializer.SerializeAsync(stream, request, requestType, opts);

                stream.Position = 0;

                using (var reader = new StreamReader(stream))
                {
                    var result = await reader.ReadToEndAsync();

                    return(result);
                }
            }
        }
예제 #18
0
        public async Task <string> SerializeRequest(BaseRequest request, Type requestType, HttpDataSerializerOptions options = null)
        {
            var    settings = JsonNetSerializerSettings.CreateJsonSerializerSettings(options, _debugMode);
            string contents = "";

            using (var stream = new MemoryStream())
            {
                using (var writer = new StreamWriter(stream, Encoding.UTF8))
                {
                    var serializer = JsonSerializer.Create(settings);
                    serializer.Serialize(writer, request, requestType);
                }

                stream.Position = 0;
                using (var reader = new StreamReader(stream, Encoding.UTF8))
                {
                    contents = await reader.ReadToEndAsync();
                }
            }

            return(contents);
        }
예제 #19
0
        public Task <IDictionary <string, string[]> > ValidateSchema(byte[] message, Type type, HttpDataSerializerOptions options = null)
        {
            options = options ?? new HttpDataSerializerOptions();
            string contents = Encoding.UTF8.GetString(message);

            var schema = GetSchema(
                type,
                options,
                options.EnumSerializationMethod == EnumSerializationMethod.String, requireReferenceTypes:
                false);

            ICollection <ValidationError>  errors = schema.Validate(contents, new EnumFormatValidator());
            IDictionary <string, string[]> dict   = new Dictionary <string, string[]>();

            foreach (var err in errors)
            {
                RecursivelyGetErrors(dict, err, schema);
            }

            if (dict.Any())
            {
                dict.AddOrAppendValue("errorType", "jsonSchemaValidation");
                dict.AddOrAppendValue("schema", schema.ToJson(Formatting.None));
                _logger.LogTrace(schema.ToJson());
            }

            return(Task.FromResult(dict));
        }
예제 #20
0
        public async Task ConvertResponse(ServiceResponse response, Type responseType, HttpResponse httpResponse, HttpDataSerializerOptions options = null)
        {
            options ??= new HttpDataSerializerOptions();
            var serializedData = await _serializer.SerializeResponse(response, responseType, options);

            var contentType = _serializer.ContentType;
            var encoding    = _serializer.Encoding;

            httpResponse.StatusCode  = response.MetaData.Result.HttpStatusCode();
            httpResponse.ContentType = contentType;

            await httpResponse.WriteAsync(serializedData, encoding);
        }
예제 #21
0
        public async Task <BaseRequest> ConvertRequest(Type requestType, HttpRequest request, HttpDataSerializerOptions options)
        {
            options ??= new HttpDataSerializerOptions();
            BaseRequest result = null;

            if (request.ContentLength.GetValueOrDefault() > 0)
            {
                await using var ms = new MemoryStream();
                await request.Body.CopyToAsync(ms);

                var message = ms.ToArray();
                result = await _serializer.DeserializeRequest(requestType, message, options);
            }

            if (request.Query.Any())
            {
                result ??= (BaseRequest)Activator.CreateInstance(requestType);
                PropertyInfo[] properties = requestType.GetProperties();
                foreach (PropertyInfo property in properties)
                {
                    StringValues qv = request.Query[property.Name];
                    if (!string.IsNullOrWhiteSpace(qv))
                    {
                        try
                        {
                            var val = GetFromString(qv, property.PropertyType);
                            property.SetValue(result, val);
                        }
                        catch (Exception)
                        {
                            throw new ValidationErrorException($"Cannot convert {qv} to {property.PropertyType.Name}", property.Name);
                        }
                    }
                }
            }

            return(result ?? (BaseRequest)Activator.CreateInstance(requestType));
        }
예제 #22
0
        public async Task ConvertResponse <T>(ServiceResponse <T> response, HttpResponse httpResponse, HttpDataSerializerOptions options) where T : new()
        {
            var serializedData = await _serializer.SerializeResponse(response, typeof(ServiceResponse <T>), options);

            var contentType = _serializer.ContentType;
            var encoding    = _serializer.Encoding;

            httpResponse.StatusCode  = response.MetaData.Result.HttpStatusCode();
            httpResponse.ContentType = contentType;

            await httpResponse.WriteAsync(serializedData, encoding);
        }