Esempio n. 1
0
 bool EqualsOnlyAny(JsonSchemaAttribute rhs)
 {
     return(EqualsSingletonOrArray <string>(Type, rhs.Type) &&
            EqualsEnumerable(Enum, rhs.Enum) &&
            Object.Equals(Const, rhs.Const)
            );
 }
Esempio n. 2
0
 bool EqualsOnlyString(JsonSchemaAttribute rhs)
 {
     return(MaxLength == rhs.MaxLength &&
            MinLength == rhs.MinLength &&
            Object.Equals(Pattern, rhs.Pattern)
            );
 }
Esempio n. 3
0
 internal static ConstraintsViolationException Validate(this JsonSchemaAttribute j,
                                                        object o,
                                                        Internal.State state,
                                                        JsonSchemaRegistory reg)
 {
     return((new JsonSchemaValidator(j)).Validate(o, state, reg));
 }
Esempio n. 4
0
 bool EqualsOnlySubBool(JsonSchemaAttribute rhs)
 {
     return(EqualsEnumerable(AllOf, rhs.AllOf) &&
            EqualsEnumerable(AnyOf, rhs.AnyOf) &&
            EqualsEnumerable(OneOf, rhs.OneOf) &&
            Object.Equals(Not, rhs.Not)
            );
 }
Esempio n. 5
0
 bool EqualsOnlyNum(JsonSchemaAttribute rhs)
 {
     return(MultipleOf == rhs.MultipleOf &&
            Maximum == rhs.Maximum &&
            ExclusiveMaximum == rhs.ExclusiveMaximum &&
            Minimum == rhs.Minimum &&
            ExclusiveMinimum == rhs.ExclusiveMinimum
            );
 }
Esempio n. 6
0
        // contains

        bool EqualsOnlyArray(JsonSchemaAttribute rhs)
        {
            return(EqualsSingletonOrArray <JsonSchemaAttribute>(Items, rhs.Items) &&
                   Object.Equals(AdditionalItems, rhs.AdditionalItems) &&
                   MaxItems == rhs.MaxItems &&
                   MinItems == rhs.MinItems &&
                   UniqueItems == rhs.UniqueItems
                   );
        }
Esempio n. 7
0
        private void AddToOneOf(JsonSchemaAttribute s)
        {
            if (OneOf == null)
            {
                OneOf = new List <JsonSchemaAttribute>();
            }

            OneOf.Add(s);
        }
Esempio n. 8
0
        private void AddToAnyOf(JsonSchemaAttribute s)
        {
            if (AnyOf == null)
            {
                AnyOf = new List <JsonSchemaAttribute>();
            }

            AnyOf.Add(s);
        }
Esempio n. 9
0
        public JsonSchemaAttribute(bool b)
        {
            if (!b)
            {
                // Equivalent to {"not": {}}
                Not = new JsonSchemaAttribute();
            }

            // Equivalent to {}
        }
Esempio n. 10
0
        public JsonSchemaAttribute Resolve(string id)
        {
            JsonSchemaAttribute j = null;

            if (_registory.TryGetValue(id, out j))
            {
                return(j);
            }

            return(null);
        }
Esempio n. 11
0
        ConstraintsViolationException ValidateObjectField(string key,
                                                          object value,
                                                          State state,
                                                          JsonSchemaRegistory reg)
        {
            var matched = false;

            if (_schema._dynamicResolverTag != null)
            {
                Type dynElemType;
                if (DynamicResolver.Find(_schema._dynamicResolverTag, key, out dynElemType))
                {
                    var dynElemSchema = JsonSchemaAttribute.CreateFromType(dynElemType, reg, true);
                    var ex            = dynElemSchema.Validate(value, state, reg);

                    if (ex != null)
                    {
                        return(new ConstraintsViolationException("DynamicResolver", ex));
                    }
                }
            }

            if (_schema.Properties != null)
            {
                JsonSchemaAttribute itemSchema = null;
                if (_schema.Properties.TryGetValue(key, out itemSchema))
                {
                    matched = true;

                    var ex = itemSchema.Validate(value, state, reg);
                    if (ex != null)
                    {
                        return(new ConstraintsViolationException("Property", ex));
                    }
                }
            }

            if (_schema.PatternProperties != null)
            {
                foreach (var pprop in _schema.PatternProperties)
                {
                    if (Regex.IsMatch(key, pprop.Key))
                    {
                        matched = true;

                        var ex = pprop.Value.Validate(value, state, reg);
                        if (ex != null)
                        {
                            return(new ConstraintsViolationException("PatternProperties", ex));
                        }
                    }
                }
            }

            if (_schema.AdditionalProperties != null && !matched)
            {
                var ex = _schema.AdditionalProperties.Validate(value, state, reg);
                if (ex != null)
                {
                    return(new ConstraintsViolationException("AdditionalProperties", ex));
                }
            }

            return(null);
        }
Esempio n. 12
0
        ConstraintsViolationException ValidateObject(object v, State state, JsonSchemaRegistory reg)
        {
            var validated = new Dictionary <string, object>();

            foreach (var kv in TypeHelper.ToKeyValues(v))
            {
                var ex = ValidateObjectField(kv.Key, kv.Value, state.NestAsElem(kv.Key), reg);
                if (ex != null)
                {
                    return(ex);
                }

                validated.Add(kv.Key, kv.Value);
            }

            if (_schema.Required != null)
            {
                var req = new HashSet <string>(_schema.Required);
                req.IntersectWith(validated.Keys);

                if (req.Count != _schema.Required.Count())
                {
                    var actual   = String.Join(", ", req.ToArray());
                    var expected = String.Join(", ", _schema.Required);
                    var msg      = state.CreateMessage("Lack of required fields(Actual: [{0}]; Expected: [{1}])",
                                                       actual, expected);
                    return(new ConstraintsViolationException(msg));
                }
            }

            if (_schema.MaxProperties != int.MinValue)
            {
                if (!(validated.Count <= _schema.MaxProperties))
                {
                    var msg = state.CreateMessage("MaxProperties assertion !({0} <= {1})",
                                                  validated.Count, _schema.MaxProperties);
                    return(new ConstraintsViolationException(msg));
                }
            }

            if (_schema.MinProperties != int.MaxValue)
            {
                if (!(validated.Count >= _schema.MinProperties))
                {
                    var msg = state.CreateMessage("MaxProperties assertion !({0} >= {1})",
                                                  validated.Count, _schema.MinProperties);
                    return(new ConstraintsViolationException(msg));
                }
            }

            if (_schema.Dependencies != null)
            {
                var strDep = _schema.Dependencies as Dictionary <string, string[]>;
                if (strDep != null)
                {
                    foreach (var va in validated)
                    {
                        string[] deps = null;
                        if (strDep.TryGetValue(va.Key, out deps))
                        {
                            var intersected = ((string[])deps.Clone()).Intersect(validated.Keys);
                            if (intersected.Count() != deps.Count())
                            {
                                var actual   = String.Join(", ", intersected.ToArray());
                                var expected = String.Join(", ", deps);
                                var msg      = state.CreateMessage("Dependencies assertion. Lack of depended fields for {0}(Actual: [{1}]; Expected: [{2}])",
                                                                   va.Key, actual, expected);
                                return(new ConstraintsViolationException(msg));
                            }
                        }
                    }
                    goto depChecked;
                }

                var schemaDep = _schema.Dependencies as Dictionary <string, JsonSchemaAttribute>;
                if (schemaDep != null)
                {
                    foreach (var va in validated)
                    {
                        JsonSchemaAttribute ext = null;
                        if (schemaDep.TryGetValue(va.Key, out ext))
                        {
                            var ex = ext.Validate(v, new State().NestAsElem(va.Key), reg);
                            if (ex != null)
                            {
                                // TODO:
                                var msg = state.CreateMessage("Dependencies assertion. Failed to validation for {0}",
                                                              va.Key);
                                return(new ConstraintsViolationException(msg, ex));
                            }
                        }
                    }
                }

depChecked:
                ;
            }

            return(null);
        }
Esempio n. 13
0
 public JsonSchemaValidator(JsonSchemaAttribute j)
 {
     _schema = j;
 }
Esempio n. 14
0
 public void Register(string id, JsonSchemaAttribute j)
 {
     _registory.Add(id, j);
 }
Esempio n. 15
0
 public static ConstraintsViolationException Validate(this JsonSchemaAttribute j,
                                                      object o,
                                                      JsonSchemaRegistory reg = null)
 {
     return((new JsonSchemaValidator(j)).Validate(o, reg));
 }
Esempio n. 16
0
        public static JsonSchemaAttribute CreateFromType(Type ty, JsonSchemaRegistory reg = null, bool asRef = false)
        {
            var kind = Node.KindOfType(ty);

            switch (kind)
            {
            case NodeKind.Boolean:
                return(new JsonSchemaAttribute
                {
                    Type = "boolean",
                });

            case NodeKind.Integer:
                object[] enumsForInteger = null;
                if (TypeHelper.TypeWrap(ty).IsEnum)
                {
                    enumsForInteger = System.Enum.GetValues(ty).Cast <object>().ToArray();
                }
                return(new JsonSchemaAttribute
                {
                    Type = "integer",
                    Enum = enumsForInteger,
                });

            case NodeKind.Float:
                return(new JsonSchemaAttribute
                {
                    Type = "number",
                });

            case NodeKind.String:
                object[] enumsForString = null;
                if (TypeHelper.TypeWrap(ty).IsEnum)
                {
                    enumsForString = TypeHelper.GetStringEnumNames(ty);
                }
                return(new JsonSchemaAttribute
                {
                    Type = "string",
                    Enum = enumsForString,
                });

            case NodeKind.Array:
                var elemTy = TypeHelper.ElemTypeOfIEnumerable(ty);
                return(new JsonSchemaAttribute
                {
                    Type = "array",
                    Items = elemTy != null?CreateFromType(elemTy, reg, true) : null,
                });

            case NodeKind.Object:
                if (ty == typeof(object))
                {
                    return(new JsonSchemaAttribute());
                }

                if (TypeHelper.TypeWrap(ty).IsGenericType&& ty.GetGenericTypeDefinition() == typeof(Dictionary <,>))
                {
                    return(new JsonSchemaAttribute
                    {
                        Type = "object",
                    });
                }

                break;

            default:
                throw new NotImplementedException();
            }

            if (reg == null)
            {
                reg = JsonSchemaRegistory.GetDefault();
            }

            var schema = TypeHelper.GetCustomAttribute <JsonSchemaAttribute>(ty);

            if (schema == null)
            {
                schema = new JsonSchemaAttribute();
            }
            schema.Type = "object";

            var schemaId = schema.Id;

            if (schemaId == null)
            {
                schemaId = ty.ToString();
            }
            var refSchema = reg.Resolve(schemaId);

            if (refSchema != null)
            {
                schema = refSchema;
                goto skip;
            }
            else
            {
                reg.Register(schemaId, schema);
            }

            var baseType = TypeHelper.TypeWrap(ty).BaseType;
            HashSet <string> baseFieldNames = null;

            if (baseType != null)
            {
                Type schemaBaseType;
                if (RefChecker.IsRefTag(baseType, out schemaBaseType))
                {
                    var baseSchemaValue = CreateFromType(schemaBaseType, reg, false);
                    schema.Type = baseSchemaValue.Type;

                    goto skip;
                }

                // Nest fields included in the base class
                var baseSchema = CreateFromType(baseType, reg, true);
                if (baseSchema != null && baseSchema.Ref != null)
                {
                    schema.AddToAllOf(baseSchema);

                    var baseFields = TypeHelper.TypeWrap(baseType).GetFields(BindingFlags.Public | BindingFlags.Instance);
                    baseFieldNames = new HashSet <string>(baseFields.Select(f => f.Name));
                }
            }

            var properties   = new Dictionary <string, JsonSchemaAttribute>();
            var required     = new List <string>();
            var dependencies = new Dictionary <string, string[]>();

            var fields = TypeHelper.TypeWrap(ty).GetFields(BindingFlags.Public | BindingFlags.Instance);

            foreach (var field in fields)
            {
                var fieldType = field.FieldType;

                JsonSchemaAttribute fieldSchema = null;
                var attr     = TypeHelper.GetCustomAttribute <JsonFieldAttribute>(field);
                var elemName = JsonFieldAttribute.FieldName(attr, field); // TODO: duplication check

                // If elements are also included in Base classes, skip collecting a schema for the elements.
                if (baseFieldNames != null && baseFieldNames.Contains(field.Name))
                {
                    fieldSchema = new JsonSchemaAttribute();
                    goto skipField;
                }

                fieldSchema = TypeHelper.GetCustomAttribute <JsonSchemaAttribute>(field);
                if (fieldSchema == null)
                {
                    fieldSchema = new JsonSchemaAttribute();
                }

                var fieldItemsSchema = TypeHelper.GetCustomAttribute <ItemsJsonSchemaAttribute>(field);
                if (fieldItemsSchema != null)
                {
                    fieldSchema.Items = fieldItemsSchema;
                }

                if (attr != null && attr.DynamicResolverTag != null)
                {
                    if (!TypeHelper.TypeWrap(fieldType).IsGenericType || fieldType.GetGenericTypeDefinition() != typeof(Dictionary <,>))
                    {
                        var baseMsg = "A type of the field which has DynamicResolver must be a Dictionary<,>";
                        var msg     = string.Format("{0}: Type = {1} at \"{2}\" of {3}", baseMsg, fieldType, elemName, ty);
                        throw new ArgumentException(msg);
                    }

                    var keyType = TypeHelper.TypeWrap(fieldType).GetGenericArguments()[0];
                    if (keyType != typeof(string))
                    {
                        var baseMsg = "A key of the dictionary which has DynamicResolver must be a string type";
                        var msg     = string.Format("{0}: KeyType = {1} at \"{2}\" of {3}", baseMsg, keyType, elemName, ty);
                        throw new ArgumentException(msg);
                    }

                    fieldSchema._dynamicResolverTag = attr.DynamicResolverTag;
                }

                var fieldItemRequired = TypeHelper.GetCustomAttribute <JsonSchemaRequiredAttribute>(field);
                if (fieldItemRequired != null)
                {
                    required.Add(elemName);
                }

                var fieldItemDependencies = TypeHelper.GetCustomAttribute <JsonSchemaDependenciesAttribute>(field);
                if (fieldItemDependencies != null)
                {
                    dependencies.Add(elemName, fieldItemDependencies.Dependencies);
                }

                var fieldTypeSchema = CreateFromType(fieldType, reg, true);
                if (fieldTypeSchema.Ref != null)
                {
                    fieldSchema = fieldTypeSchema;
                }
                else
                {
                    // Update
                    if (fieldSchema.Type == null)
                    {
                        fieldSchema.Type = fieldTypeSchema.Type;
                    }

                    if (fieldSchema.Enum == null)
                    {
                        fieldSchema.Enum = fieldTypeSchema.Enum;
                    }

                    if (fieldTypeSchema.Items != null)
                    {
                        var fieldTypeSchemaItems = fieldTypeSchema.Items as JsonSchemaAttribute;
                        if (fieldTypeSchemaItems.Ref != null)
                        {
                            fieldSchema.Items = fieldTypeSchemaItems;
                        }
                        else
                        {
                            if (fieldTypeSchemaItems.Type != null)
                            {
                                var fieldSchemaItems = fieldSchema.Items as JsonSchemaAttribute;
                                if (fieldSchemaItems != null)
                                {
                                    fieldSchemaItems.Type = fieldTypeSchemaItems.Type;
                                }
                                else
                                {
                                    fieldSchema.Items = new JsonSchemaAttribute
                                    {
                                        Type = fieldTypeSchemaItems.Type,
                                    };
                                }
                            }

                            if (fieldTypeSchemaItems.Enum != null)
                            {
                                var fieldSchemaItems = fieldSchema.Items as JsonSchemaAttribute;
                                fieldSchemaItems.Enum = fieldTypeSchemaItems.Enum;
                            }
                        }
                    }
                }

                // Add custom refs to AllOf not to override constrains which already existing.
                var customRef = TypeHelper.GetCustomAttribute <JsonSchemaRefAttribute>(field);
                if (customRef != null)
                {
                    Type schemaBaseType;
                    if (!RefChecker.IsRefTagDerived(customRef.TagType, out schemaBaseType))
                    {
                        throw new ArgumentException("IRefTag<T> must be derived by tagType");
                    }

                    var customSchema = CreateFromType(customRef.TagType, reg, true);
                    switch (customRef.Influence)
                    {
                    case InfluenceRange.Entiry:
                        fieldSchema.AddToAllOf(customSchema);
                        break;

                    case InfluenceRange.AdditionalProperties:
                        if (fieldSchema.AdditionalProperties == null)
                        {
                            fieldSchema.AdditionalProperties = new JsonSchemaAttribute();
                        }
                        fieldSchema.AdditionalProperties.AddToAllOf(customSchema);
                        break;
                    }
                }

                // Add custom refs to AllOf not to override constrains which already existing.
                var customItemsRef = TypeHelper.GetCustomAttribute <ItemsJsonSchemaRefAttribute>(field);
                if (customItemsRef != null)
                {
                    Type schemaBaseType;
                    if (!RefChecker.IsRefTagDerived(customItemsRef.TagType, out schemaBaseType))
                    {
                        throw new ArgumentException("IRefTag<T> must be derived by tagType");
                    }

                    var customSchema = CreateFromType(customItemsRef.TagType, reg, true);
                    switch (customItemsRef.Influence)
                    {
                    case InfluenceRange.Entiry:
                        if (fieldSchema.Items == null)
                        {
                            fieldSchema.Items = new JsonSchemaAttribute();
                        }
                        ((JsonSchemaAttribute)fieldSchema.Items).AddToAllOf(customSchema);
                        break;

                    case InfluenceRange.AdditionalProperties:
                        if (fieldSchema.Items == null)
                        {
                            fieldSchema.Items = new JsonSchemaAttribute();
                        }
                        if (((JsonSchemaAttribute)fieldSchema.Items).AdditionalProperties == null)
                        {
                            ((JsonSchemaAttribute)fieldSchema.Items).AdditionalProperties =
                                new JsonSchemaAttribute();
                        }
                        ((JsonSchemaAttribute)fieldSchema.Items).AdditionalProperties.AddToAllOf(customSchema);
                        break;
                    }
                }

skipField:
                properties.Add(elemName, fieldSchema);
            }

            schema.Properties = properties;
            if (required.Count != 0)
            {
                schema.Required = required.ToArray();
            }
            if (dependencies.Count != 0)
            {
                schema.Dependencies = dependencies;
            }

skip:
            if (asRef)
            {
                return(new JsonSchemaAttribute
                {
                    Ref = schemaId,
                });
            }

            return(schema);
        }
Esempio n. 17
0
        public object Dependencies; // Use [JsonSchemaDependencies] instead when specify it by attributes.

        // propertyNames

        bool EqualsOnlyObject(JsonSchemaAttribute rhs)
        {
            // TODO
            return(true);
        }