예제 #1
0
        /// <summary>
        /// Converts a Json Schema string to a <see cref="ModelMetadata"/>
        /// </summary>
        /// <param name="modelName">The name of the model.</param>
        /// <param name="jsonSchema">The Json Schema to be converted</param>
        /// <returns>An flattened representation of the Json Schema in the form of <see cref="ModelMetadata"/></returns>
        public ModelMetadata Convert(string modelName, string jsonSchema)
        {
            ModelName = modelName;

            _modelMetadata = new ModelMetadata();
            _schema        = JsonSchema.FromText(jsonSchema);
            var schemaUri = _schema.GetKeyword <IdKeyword>().Id;

            _schemaXsdMetadata = _schemaAnalyzer.AnalyzeSchema(_schema, schemaUri);

            ProcessSchema(_schema);

            return(_modelMetadata);
        }
예제 #2
0
        /// <summary>
        /// Determines the type of root model the provided schema has.
        /// </summary>
        /// <param name="schema">The Json Schema to analyze.</param>
        protected void DetermineRootModel(JsonSchema schema)
        {
            Metadata.HasInlineRoot = true;

            var allOf = schema.GetKeyword <AllOfKeyword>();
            var anyOf = schema.GetKeyword <AnyOfKeyword>();
            var oneOf = schema.GetKeyword <OneOfKeyword>();

            if (allOf != null && anyOf == null && oneOf == null)
            {
                // Only "allOf"
                Metadata.HasInlineRoot = !(allOf.Schemas.Count == 1 && IsRefSchema(allOf.Schemas[0]));
            }
            else if (allOf == null && anyOf != null && oneOf == null)
            {
                // Only "anyOf"
                Metadata.HasInlineRoot = !(anyOf.Schemas.Count == 1 && IsRefSchema(anyOf.Schemas[0]));
            }
            else if (allOf == null && anyOf == null && oneOf != null)
            {
                // Only "oneOf"
                Metadata.HasInlineRoot = !(oneOf.Schemas.Count == 1 && IsRefSchema(oneOf.Schemas[0]));
            }
        }
예제 #3
0
        public void Constructor_TemplateExists_ShouldSetCorrectValues()
        {
            // Arrange
            JsonSchemaKeywords.RegisterXsdKeywords();

            var expectedId = "https://dev.altinn.studio/org/repository/app/model/model.schema.json";

            // Act
            var actualJsonTemplate = new SeresJsonTemplate(new Uri(expectedId), "melding");

            // Assert
            JsonSchema jsonSchema = JsonSchema.FromText(actualJsonTemplate.GetJsonString());
            var        idKeyword  = jsonSchema.GetKeyword <IdKeyword>();

            idKeyword.Id.Should().Be(expectedId);

            var infoKeyword = jsonSchema.GetKeyword <InfoKeyword>();
            var value       = infoKeyword.Value;

            value.GetProperty("meldingsnavn").GetString().Should().Be("melding");
            value.GetProperty("modellnavn").GetString().Should().Be("melding-modell");

            var messageType = jsonSchema.FollowReference(JsonPointer.Parse("#/$defs/melding-modell")).Should().NotBeNull();
        }
예제 #4
0
        /// <summary>
        /// Tries to parse a schema to verify if it an array and returns the item schema if it is.
        /// For furter reference see https://json-schema.org/understanding-json-schema/reference/array.html
        /// </summary>
        /// <param name="schema">The Json Schema to analyze.</param>
        /// <param name="itemsSchema">If the schema is an array this will return schema for the items in the array; otherwise, null.</param>
        /// <returns>True if the schema is an array; otherwise, false</returns>
        protected static bool TryParseAsArray(JsonSchema schema, out JsonSchema itemsSchema)
        {
            if (schema.TryGetKeyword(out TypeKeyword typeKeyword) && typeKeyword.Type.HasFlag(SchemaValueType.Array))
            {
                var itemsKeyword = schema.GetKeyword <ItemsKeyword>();
                if (itemsKeyword == null)
                {
                    throw new JsonSchemaConvertException("Schema must have an \"items\" keyword when \"type\" is set to array");
                }

                itemsSchema = itemsKeyword.SingleSchema;
                return(true);
            }

            itemsSchema = null;
            return(false);
        }
예제 #5
0
        private static List <(string PropertyName, JsonSchema PropertySchema)> FindSimpleContentProperties(JsonSchema schema)
        {
            var properties = new List <(string PropertyName, JsonSchema PropertySchema)>();

            if (HasSingleAllOf(schema))
            {
                foreach (var propertiesSchema in schema.GetKeyword <AllOfKeyword>().Schemas.Where(s => s.HasKeyword <PropertiesKeyword>()))
                {
                    var propertiesKeyword = propertiesSchema.GetKeyword <PropertiesKeyword>();
                    properties.AddRange(propertiesKeyword.Properties.Select(prop => (prop.Key, prop.Value)));
                }
            }
            else if (schema.TryGetKeyword(out PropertiesKeyword propertiesKeyword))
            {
                properties.AddRange(propertiesKeyword.Properties.Select(prop => (prop.Key, prop.Value)));
            }

            return(properties);
        }
예제 #6
0
        /// <summary>
        /// Determines if the schema should be represented as a SimpleContentRestriction in the XSD.
        /// </summary>
        /// <param name="schema">The Json Schema to analyze.</param>
        /// <returns>True if it should be represented as a SimpleContentRestriction in the XSD; otherwise, false.</returns>
        protected bool IsValidSimpleContentRestriction(JsonSchema schema)
        {
            if (!HasSingleAllOf(schema))
            {
                return(false);
            }

            var allOf = schema.GetKeyword <AllOfKeyword>();
            var baseReferenceSchemas = allOf.Schemas.Where(s => s.HasKeyword <RefKeyword>()).ToList();

            if (baseReferenceSchemas.Count != 1)
            {
                return(false);
            }

            var baseReferenceSchema = baseReferenceSchemas[0];
            var baseSchema          = FollowReference(baseReferenceSchema.GetKeyword <RefKeyword>());

            // Make sure base is valid for SimpleContent restriction
            if (!IsValidSimpleContentExtension(baseSchema) && !IsValidSimpleContentRestriction(baseSchema))
            {
                return(false);
            }

            var propertiesSchemas = allOf.Schemas.Where(s => s.HasKeyword <PropertiesKeyword>()).ToList();

            // Don't allow extra subschemas not used in the pattern
            if (propertiesSchemas.Count + 1 != allOf.Schemas.Count)
            {
                return(false);
            }

            // All restriction properties must match properties from base type(s)
            var basePropertyNames = new HashSet <string>();

            while (!IsValidSimpleType(baseSchema))
            {
                foreach (var(propertyName, _) in FindSimpleContentProperties(baseSchema))
                {
                    basePropertyNames.Add(propertyName);
                }

                if (!baseSchema.TryGetKeyword(out AllOfKeyword baseAllOf))
                {
                    break;
                }

                var baseRefSchema = baseAllOf.Schemas
                                    .SingleOrDefault(s => s.HasKeyword <RefKeyword>())
                                    ?.GetKeyword <RefKeyword>();

                if (baseRefSchema == null)
                {
                    break;
                }

                baseSchema = FollowReference(baseRefSchema);
            }

            var hasValueProperty = false;

            foreach (var(propertyName, propertySchema) in propertiesSchemas.SelectMany(ps => ps.GetKeyword <PropertiesKeyword>().Properties.Select(prop => (prop.Key, prop.Value))))
            {
                if (!basePropertyNames.Contains(propertyName))
                {
                    // Can't restrict a property that is not present in base types, this is not a valid simple content restriction
                    return(false);
                }

                var propertyTargetSchema = FollowReferencesIfAny(propertySchema);

                if (!hasValueProperty && propertyName == "value")
                {
                    // "value" property
                    hasValueProperty = true;

                    // "value" property cannot be an attribute
                    if (propertySchema.HasKeyword <XsdAttributeKeyword>())
                    {
                        return(false);
                    }
                }
                else
                {
                    // restriction property must be an attribute
                    if (!propertySchema.HasKeyword <XsdAttributeKeyword>())
                    {
                        return(false);
                    }
                }

                if (!IsValidSimpleTypeOrSimpleTypeRestriction(propertyTargetSchema) && !IsPlainRestrictionSchema(propertyTargetSchema))
                {
                    return(false);
                }
            }

            return(hasValueProperty);
        }