Exemplo n.º 1
0
        private CodeTypeDeclaration GenerateClass()
        {
            if (!context.ContainsKey(schema))
            {
                context.Add(schema, new GenerationResult()
                {
                    TypeName       = targetClass.Name,
                    Type           = MyTypeBuilder.CreateType(targetClass.Name),
                    ClassGenerator = this
                });
            }

            if (schema.Enum?.Count > 0)
            {
                return(GenerateClassFromEnumSchema());
            }

            if (schema.Type?.Value is SimpleType && (schema.Type.Value as SimpleType).Value != SimpleType.Object)
            {
                var schemaType = schema.Type.Value as SimpleType;
                if (schemaType.Value == SimpleType.Integer)
                {
                    return(GenerateClassFromIntegerSchema());
                }

                if (schemaType.Value == SimpleType.Number)
                {
                    return(GenerateClassFromNumberSchema());
                }

                if (schemaType.Value == SimpleType.String)
                {
                    return(GenerateClassFromStringSchema());
                }

                if (schemaType.Value == SimpleType.Array)
                {
                    return(GenerateClassFromArraySchema());
                }
            }
            var definitions = schema.Definitions;

            if (definitions != null)
            {
                foreach (string definitionName in schema.Definitions.Keys)
                {
                    var definition = definitions[definitionName];
                    if (!context.ContainsKey(definition))
                    {
                        var nestedClassGenerator = new ClassGeneratorFromJsonSchema(definition, context);
                        context[definition] = new GenerationResult()
                        {
                            Type           = MyTypeBuilder.CreateType(nestedClassGenerator.targetClass.Name),
                            TypeName       = nestedClassGenerator.targetClass.Name,
                            ClassGenerator = nestedClassGenerator
                        };
                        nestedClassGenerator.GenerateClass();
                    }
                    //context.Add(definition, new GenerationResult() { TypeName = nestedClassGenerator.targetClass.Name });
                }
            }

            var properties           = schema.Properties;
            var additionalProperties = schema.AdditionalProperties;

            //Oneof/AnyOf/AllOf are only supported when there are no properties or additionalProperties and when the schema type is not a primitive type or array type
            if (properties == null && additionalProperties == null)
            {
                if (schema.OneOf != null && schema.OneOf.Count > 0)
                {
                    return(GenerateClassFromOneOfAnyOfSchema(true));
                }

                if (schema.AnyOf != null && schema.AnyOf.Count > 0)
                {
                    return(GenerateClassFromOneOfAnyOfSchema(false));
                }

                if (schema.AllOf != null && schema.AllOf.Count > 0)
                {
                    var mergedSchema         = JSONSchema.MergeSchemas(schema.AllOf);
                    var mergedClassGenerator = new ClassGeneratorFromJsonSchema(mergedSchema, this.targetClass.Name);
                    targetClass     = mergedClassGenerator.GenerateClass();
                    context[schema] = mergedClassGenerator.context[mergedSchema];
                    foreach (var jsonSchema in mergedClassGenerator.context.Keys)
                    {
                        if (jsonSchema != mergedSchema)
                        {
                            context[jsonSchema] = mergedClassGenerator.context[jsonSchema];
                        }
                    }
                    return(targetClass);
                }
            }

            if (properties != null)
            {
                foreach (string propertyName in properties.Keys)
                {
                    var cleanPropertyName = Clean(propertyName);
                    if (propertyNames.Contains(cleanPropertyName))
                    {
                        //to avoid property names that would collide
                        continue;
                    }
                    propertyNames.Add(cleanPropertyName);
                    var property = properties[propertyName];

                    if (context.ContainsKey(property))
                    {
                        targetClass.AddProperty(cleanPropertyName, context[property].TypeName);
                    }
                    else if (property.Type?.GetUnderlyingType() == typeof(SimpleType) &&
                             (property.Type.Value as SimpleType).Value != SimpleType.Object &&
                             (property.Type.Value as SimpleType).Value != SimpleType.Array &&
                             (property.Enum == null || property.Enum.Count < 1)
                             )
                    {
                        targetClass.AddProperty(cleanPropertyName, ComputeType((SimpleType)property.Type.GetValue()));
                    }
                    else
                    {
                        var nestedClassGenerator = new ClassGeneratorFromJsonSchema(property, context, cleanPropertyName);
                        context[property] = new GenerationResult()
                        {
                            Type           = MyTypeBuilder.CreateType(nestedClassGenerator.targetClass.Name),
                            TypeName       = nestedClassGenerator.targetClass.Name,
                            ClassGenerator = nestedClassGenerator
                        };
                        nestedClassGenerator.GenerateClass();
                        targetClass.AddProperty(cleanPropertyName, context[property].Type);
                    }
                }
            }


            if (additionalProperties != null)
            {
                if (additionalProperties.Value is bool)
                {
                    if ((bool)additionalProperties.Value == true)
                    {
                        targetClass.BaseTypes.Add(new CodeTypeReference(typeof(Dictionary <string, object>)));
                    }
                }
                else
                {
                    var additionalPropertiesSchema = additionalProperties.Value as JSONSchema;
                    if (!context.ContainsKey(additionalPropertiesSchema))
                    {
                        var nestedClassGenerator = new ClassGeneratorFromJsonSchema(additionalPropertiesSchema, context, context[schema].TypeName + "AdditionalProperties");
                        context[additionalPropertiesSchema] = new GenerationResult()
                        {
                            Type           = MyTypeBuilder.CreateType(nestedClassGenerator.targetClass.Name),
                            TypeName       = nestedClassGenerator.targetClass.Name,
                            ClassGenerator = nestedClassGenerator
                        };
                        nestedClassGenerator.GenerateClass();
                    }
                    targetClass.BaseTypes.Add(new CodeTypeReference("Dictionary", new CodeTypeReference(typeof(string)), new CodeTypeReference(context[additionalPropertiesSchema].Type)));
                    context[schema].Imports.Add("System.Collections.Generic");
                }
            }



            return(targetClass);
        }
Exemplo n.º 2
0
        private CodeTypeDeclaration GenerateClassFromOneOfAnyOfSchema(bool handleOneOf)
        {
            ISet <string> subSchemasSet = new HashSet <string>();
            int           index         = 0;
            var           schemaArray   = handleOneOf ? schema.OneOf : schema.AnyOf;

            foreach (JSONSchema subSchema in schemaArray)
            {
                if (context.ContainsKey(subSchema))
                {
                    subSchemasSet.Add(context[subSchema].TypeName);
                }
                else if (subSchema.Type?.GetUnderlyingType() == typeof(SimpleType) &&
                         (subSchema.Type.Value as SimpleType).Value != SimpleType.Object &&
                         (subSchema.Type.Value as SimpleType).Value != SimpleType.Array
                         )
                {
                    subSchemasSet.Add(ComputeType((SimpleType)subSchema.Type.GetValue()).Name);
                }
                else
                {
                    var nestedClassGenerator = new ClassGeneratorFromJsonSchema(subSchema, context, string.Concat(targetClass.Name, handleOneOf?"OneOf":"AnyOf", index));
                    context[subSchema] = new GenerationResult()
                    {
                        Type           = MyTypeBuilder.CreateType(nestedClassGenerator.targetClass.Name),
                        TypeName       = nestedClassGenerator.targetClass.Name,
                        ClassGenerator = nestedClassGenerator
                    };
                    nestedClassGenerator.GenerateClass();
                    subSchemasSet.Add(nestedClassGenerator.targetClass.Name);
                }
                index++;
            }


            targetClass = new CodeTypeDeclaration(targetClass.Name)
            {
                IsClass        = true,
                TypeAttributes = TypeAttributes.Public
            };

            var field = new CodeMemberField()
            {
                Attributes = MemberAttributes.Private | MemberAttributes.Final,
                Name       = "Value",
                Type       = new CodeTypeReference(typeof(object))
            };

            targetClass.Members.Add(field);

            CodeConstructor constructor = new CodeConstructor
            {
                Attributes = MemberAttributes.Private
            };

            constructor.Comments.Add(new CodeCommentStatement("Hiding visiblity of default constructor"));
            targetClass.Members.Add(constructor);

            CodeStatement[] codeStatements = new CodeStatement[subSchemasSet.Count + 1];
            index = 0;
            foreach (string subSchemaName in subSchemasSet)
            {
                codeStatements[index] = If(NewSnippet("value is " + subSchemaName), new CodeAssignStatement(new CodeVariableReferenceExpression("Value"), new CodeVariableReferenceExpression("value")));
                index++;
            }
            codeStatements[index] = Throw(typeof(ArgumentException), "Value's type is not correct");

            CodeConstructor publicConstructor = NewPublicConstructor(
                Array(NewParameter(typeof(object), "value")),
                codeStatements
                );

            targetClass.Members.Add(publicConstructor);

            foreach (string subSchemaName in subSchemasSet)
            {
                var implicitOperator = new CodeSnippetTypeMember(string.Format("\t\tpublic static implicit operator {0}({1} d) => ({0})d.Value;", subSchemaName, targetClass.Name));
                targetClass.Members.Add(implicitOperator);

                var explicitOperator = new CodeSnippetTypeMember(string.Format("\t\tpublic static explicit operator {0}({1} v) => new {0}(v);", targetClass.Name, subSchemaName));
                targetClass.Members.Add(explicitOperator);
            }

            return(targetClass);
        }