コード例 #1
0
        private static void PatchForObject(JsonElement orig, JsonElement mod, List <PatchOperation> patch, JsonPointer path)
        {
            var origNames = orig.EnumerateObject().Select(x => x.Name).ToArray();
            var modNames  = mod.EnumerateObject().Select(x => x.Name).ToArray();

            foreach (var k in origNames.Except(modNames))
            {
                patch.Add(PatchOperation.Remove(path.Combine(k)));
            }

            foreach (var k in modNames.Except(origNames))
            {
                var prop = mod.EnumerateObject().First(p => p.NameEquals(k));
                patch.Add(PatchOperation.Add(path.Combine(k), prop.Value));
            }

            foreach (var k in origNames.Intersect(modNames))
            {
                var origProp = orig.EnumerateObject().First(p => p.NameEquals(k));
                var modProp  = mod.EnumerateObject().First(p => p.NameEquals(k));

                if (origProp.Value.ValueKind != modProp.Value.ValueKind)
                {
                    patch.Add(PatchOperation.Replace(JsonPointer.Parse(path + modProp.Name), modProp.Value));
                }
                else if (!string.Equals(origProp.Value.ToString(), modProp.Value.ToString()))                 // TODO
                {
                    if (origProp.Value.ValueKind == JsonValueKind.Object)
                    {
                        PatchForObject(origProp.Value, modProp.Value, patch, path.Combine(modProp.Name));
                    }
                    else if (origProp.Value.ValueKind == JsonValueKind.Array)
                    {
                        PatchForArray(origProp.Value, modProp.Value, patch, path.Combine(modProp.Name));
                    }
                    else
                    {
                        patch.Add(PatchOperation.Replace(path.Combine(modProp.Name), modProp.Value));
                    }
                }
            }
        }
コード例 #2
0
        private void ProcessRefKeyword(JsonPointer path, RefKeyword keyword, SchemaContext context)
        {
            int subSchemaIndex = 0;

            foreach (var subSchema in keyword.GetSubschemas())
            {
                var subSchemaPath = path.Combine(JsonPointer.Parse($"/[{subSchemaIndex}]"));
                ProcessSubSchema(subSchemaPath, subSchema, context);

                subSchemaIndex++;
            }
        }
コード例 #3
0
        /// <summary>
        /// Recursively analyzes all schemas for the provided keyword.
        /// </summary>
        /// <param name="path"><see cref="JsonPointer"/> representing the actual path to the keyword being provided.</param>
        /// <param name="keyword">The keyword to be analyzed.</param>
        protected void AnalyzeKeyword(JsonPointer path, IJsonSchemaKeyword keyword)
        {
            switch (keyword)
            {
            case AllOfKeyword item:
                for (var i = 0; i < item.Schemas.Count; i++)
                {
                    AnalyzeSchema(path.Combine(JsonPointer.Parse($"/[{i}]")), item.Schemas[i]);
                }

                break;

            case AnyOfKeyword item:
                for (var i = 0; i < item.Schemas.Count; i++)
                {
                    AnalyzeSchema(path.Combine(JsonPointer.Parse($"/[{i}]")), item.Schemas[i]);
                }

                break;

            case OneOfKeyword item:
                for (var i = 0; i < item.Schemas.Count; i++)
                {
                    AnalyzeSchema(path.Combine(JsonPointer.Parse($"/[{i}]")), item.Schemas[i]);
                }

                break;

            case DefinitionsKeyword item:
                foreach (var(name, definition) in item.Definitions)
                {
                    AnalyzeSchema(path.Combine(JsonPointer.Parse($"/{name}")), definition);
                }

                break;

            case DefsKeyword item:
                foreach (var(name, definition) in item.Definitions)
                {
                    AnalyzeSchema(path.Combine(JsonPointer.Parse($"/{name}")), definition);
                }

                break;

            case PropertiesKeyword item:
                foreach (var(name, definition) in item.Properties)
                {
                    AnalyzeSchema(path.Combine(JsonPointer.Parse($"/{name}")), definition);
                }

                break;

            case ISchemaContainer schemaContainer:
                AnalyzeSchema(path, schemaContainer.Schema);
                break;
            }
        }
コード例 #4
0
        private void ProcessOneOfKeyword(JsonPointer path, OneOfKeyword keyword, SchemaContext context)
        {
            // A oneOf keyword with only one subschema which isn't null makes it required
            if (KeywordHasSingleNonNullSchema(keyword))
            {
                AddRequiredProperties(context.Id, new List <string>()
                {
                    context.Name
                });
            }

            int subSchemaIndex = 0;

            foreach (var subSchema in keyword.GetSubschemas())
            {
                var subSchemaPath = path.Combine(JsonPointer.Parse($"/[{subSchemaIndex}]"));
                ProcessSubSchema(subSchemaPath, subSchema, context);

                subSchemaIndex++;
            }
        }
コード例 #5
0
        private static void PatchForArray(JsonElement orig, JsonElement mod, List <PatchOperation> patch, JsonPointer path)
        {
            for (int i = 0; i < Math.Max(orig.GetArrayLength(), mod.GetArrayLength()); i++)
            {
                var ui = (uint)i;
                if (i >= orig.GetArrayLength())
                {
                    patch.Add(PatchOperation.Add(path.Combine(ui), mod[i]));
                    continue;
                }

                if (i >= mod.GetArrayLength())
                {
                    patch.Add(PatchOperation.Remove(path.Combine(ui)));
                    continue;
                }

                var origObject = orig[i];
                var modObject  = mod[i];

                if (origObject.ValueKind != modObject.ValueKind)
                {
                    patch.Add(PatchOperation.Replace(path.Combine("/" + i), modObject));
                }
                else if (!string.Equals(origObject.ToString(), modObject.ToString()))                 // TODO
                {
                    if (origObject.ValueKind == JsonValueKind.Object)
                    {
                        PatchForObject(origObject, modObject, patch, path.Combine(ui));
                    }
                    else if (origObject.ValueKind == JsonValueKind.Array)
                    {
                        PatchForArray(origObject, modObject, patch, path.Combine(ui));
                    }
                    else
                    {
                        patch.Add(PatchOperation.Replace(path.Combine(ui), modObject));
                    }
                }
            }
        }
コード例 #6
0
        /// <summary>
        /// Primary method to call for analyzing a Json Schema.
        /// </summary>
        /// <param name="path">The path to start analyzing. Normally this should be the root path when calling this method ie. '#'</param>
        /// <param name="schema">The Json Schema to analyze.</param>
        protected void AnalyzeSchema(JsonPointer path, JsonSchema schema)
        {
            if (TryParseAsNillableElement(schema, out var valueSchema))
            {
                Metadata.AddCompatibleTypes(path, CompatibleXsdType.Nillable);
                if (valueSchema != null)
                {
                    AnalyzeSchema(path, valueSchema);
                    return;
                }
            }

            if (TryParseAsArray(schema, out var itemSchema))
            {
                Metadata.AddCompatibleTypes(path, CompatibleXsdType.Array);
                AnalyzeSchema(path, itemSchema);
                return;
            }

            // Follow all references, this will mark the schema as the type referenced if it has a $ref keyword
            // This will analyze some schemas multiple times and can be optimized if needed
            schema = FollowReferencesIfAny(schema);

            if (IsValidSimpleType(schema))
            {
                Metadata.AddCompatibleTypes(path, CompatibleXsdType.SimpleType);

                if (IsValidAttribute(schema))
                {
                    Metadata.AddCompatibleTypes(path, CompatibleXsdType.Attribute);
                }

                if (IsValidUnhandledAttribute(schema))
                {
                    Metadata.AddCompatibleTypes(path, CompatibleXsdType.UnhandledAttribute);
                }
            }

            if (IsValidSimpleTypeRestriction(schema))
            {
                Metadata.AddCompatibleTypes(path, CompatibleXsdType.SimpleType);
                Metadata.AddCompatibleTypes(path, CompatibleXsdType.SimpleTypeRestriction);
            }

            if (IsValidComplexType(schema))
            {
                Metadata.AddCompatibleTypes(path, CompatibleXsdType.ComplexType);
            }

            if (IsValidSimpleContentExtension(schema))
            {
                Metadata.AddCompatibleTypes(path, CompatibleXsdType.SimpleContentExtension);
            }

            if (IsValidSimpleContentRestriction(schema))
            {
                Metadata.AddCompatibleTypes(path, CompatibleXsdType.SimpleContentRestriction);
            }

            if (IsValidComplexContentExtension(path, schema))
            {
                Metadata.AddCompatibleTypes(path, CompatibleXsdType.ComplexContent);
                Metadata.AddCompatibleTypes(path, CompatibleXsdType.ComplexContentExtension);
            }

            if (schema.Keywords != null)
            {
                foreach (var keyword in schema.Keywords)
                {
                    var keywordPath = path.Combine(JsonPointer.Parse($"/{keyword.Keyword()}"));
                    AnalyzeKeyword(keywordPath, keyword);
                }
            }

            if (IsValidUnhandledAttribute(schema))
            {
                Metadata.AddCompatibleTypes(path, CompatibleXsdType.UnhandledAttribute);
            }

            if (IsValidUnhandledEnumAttribute(schema))
            {
                Metadata.AddCompatibleTypes(path, CompatibleXsdType.UnhandledEnumAttribute);
            }

            // Add "unknown" if no other was added on this path
            if (Metadata.GetCompatibleTypes(path).Count == 0)
            {
                Metadata.AddCompatibleTypes(path, CompatibleXsdType.Unknown);
            }
        }