Beispiel #1
0
func (g openAPITypeWriter) generateMapProperty(t *types.Type) error {
	keyType := resolveAliasAndPtrType(t.Key)
	elemType := resolveAliasAndPtrType(t.Elem)

	// According to OpenAPI examples, only map from string is supported
	if keyType.Name.Name != "string" {
		return fmt.Errorf("map with non-string keys are not supported by OpenAPI in %v", t)
	}
	g.Do("Type: []string{\"object\"},\n", nil)
	g.Do("AdditionalProperties: &spec.SchemaOrBool{\nSchema: &spec.Schema{\nSchemaProps: spec.SchemaProps{\n", nil)
	typeString, format := common.GetOpenAPITypeFormat(elemType.String())
	if typeString != "" {
		g.generateSimpleProperty(typeString, format)
		g.Do("},\n},\n},\n", nil)
		return nil
	}
	switch elemType.Kind {
	case types.Builtin:
		return fmt.Errorf("please add type %v to getOpenAPITypeFormat function.", elemType)
	case types.Struct:
		g.generateReferenceProperty(t.Elem)
	case types.Slice, types.Array:
		g.generateSliceProperty(elemType)
	default:
		return fmt.Errorf("map Element kind %v is not supported in %v", elemType.Kind, t.Name)
	}
	g.Do("},\n},\n},\n", nil)
	return nil
}
func (g openAPITypeWriter) generate(t *types.Type) error {
	// Only generate for struct type and ignore the rest
	switch t.Kind {
	case types.Struct:
		args := argsFromType(t)
		g.Do("\"$.$\": ", typeShortName(t))
		if hasOpenAPIDefinitionMethod(t) {
			g.Do("$.type|raw${}.OpenAPIDefinition(),", args)
			return nil
		}
		g.Do("{\nSchema: spec.Schema{\nSchemaProps: spec.SchemaProps{\n", nil)
		g.generateDescription(t.CommentLines)
		g.Do("Properties: map[string]$.SpecSchemaType|raw${\n", args)
		required := []string{}
		for _, m := range t.Members {
			if hasOpenAPITagValue(m.CommentLines, tagValueFalse) {
				continue
			}
			name := getReferableName(&m)
			if name == "" {
				continue
			}
			if !hasOptionalTag(m.CommentLines) {
				required = append(required, name)
			}
			if err := g.generateProperty(&m); err != nil {
				return err
			}
		}
		g.Do("},\n", nil)
		if len(required) > 0 {
			g.Do("Required: []string{\"$.$\"},\n", strings.Join(required, "\",\""))
		}
		g.Do("},\n},\n", nil)
		g.Do("Dependencies: []string{\n", args)
		// Map order is undefined, sort them or we may get a different file generated each time.
		keys := []string{}
		for k := range g.refTypes {
			keys = append(keys, k)
		}
		sort.Strings(keys)
		for _, k := range keys {
			v := g.refTypes[k]
			if t, _ := common.GetOpenAPITypeFormat(v.String()); t != "" {
				// This is a known type, we do not need a reference to it
				// Will eliminate special case of time.Time
				continue
			}
			g.Do("\"$.$\",", k)
		}
		g.Do("},\n},\n", nil)
	}
	return nil
}
func (g openAPITypeWriter) generateSliceProperty(t *types.Type) error {
	elemType := resolveAliasAndPtrType(t.Elem)
	g.Do("Type: []string{\"array\"},\n", nil)
	g.Do("Items: &spec.SchemaOrArray{\nSchema: &spec.Schema{\nSchemaProps: spec.SchemaProps{\n", nil)
	switch elemType.Kind {
	case types.Builtin:
		typeString, format := common.GetOpenAPITypeFormat(elemType.String())
		g.generateSimpleProperty(typeString, format)
	case types.Struct:
		g.generateReferenceProperty(t.Elem)
	default:
		return fmt.Errorf("slice Element kind %v is not supported in %v", elemType.Kind, t)
	}
	g.Do("},\n},\n},\n", nil)
	return nil
}
func (g openAPITypeWriter) generateProperty(m *types.Member) error {
	name := getReferableName(m)
	if name == "" {
		return nil
	}
	g.Do("\"$.$\": {\n", name)
	g.Do("SchemaProps: spec.SchemaProps{\n", nil)
	g.generateDescription(m.CommentLines)
	jsonTags := getJsonTags(m)
	if len(jsonTags) > 1 && jsonTags[1] == "string" {
		g.generateSimpleProperty("string", "")
		g.Do("},\n},\n", nil)
		return nil
	}
	t := resolveAliasAndPtrType(m.Type)
	// If we can get a openAPI type and format for this type, we consider it to be simple property
	typeString, format := common.GetOpenAPITypeFormat(t.String())
	if typeString != "" {
		g.generateSimpleProperty(typeString, format)
		g.Do("},\n},\n", nil)
		return nil
	}
	switch t.Kind {
	case types.Builtin:
		return fmt.Errorf("please add type %v to getOpenAPITypeFormat function.", t)
	case types.Map:
		if err := g.generateMapProperty(t); err != nil {
			return err
		}
	case types.Slice, types.Array:
		if err := g.generateSliceProperty(t); err != nil {
			return err
		}
	case types.Struct, types.Interface:
		g.generateReferenceProperty(t)
	default:
		return fmt.Errorf("cannot generate spec for type %v.", t)
	}
	g.Do("},\n},\n", nil)
	return g.Error()
}
Beispiel #5
0
func (o *openAPI) toSchema(typeName string, model interface{}) (_ *spec.Schema, err error) {
	if openAPIType, openAPIFormat := common.GetOpenAPITypeFormat(typeName); openAPIType != "" {
		return &spec.Schema{
			SchemaProps: spec.SchemaProps{
				Type:   []string{openAPIType},
				Format: openAPIFormat,
			},
		}, nil
	} else {
		ref := "#/definitions/" + typeName
		if model != nil {
			ref, err = o.buildDefinitionForType(model)
			if err != nil {
				return nil, err
			}
		}
		return &spec.Schema{
			SchemaProps: spec.SchemaProps{
				Ref: spec.MustCreateRef(ref),
			},
		}, nil
	}
}
Beispiel #6
0
func (o *openAPI) buildParameter(restParam restful.ParameterData) (ret spec.Parameter, err error) {
	ret = spec.Parameter{
		ParamProps: spec.ParamProps{
			Name:        restParam.Name,
			Description: restParam.Description,
			Required:    restParam.Required,
		},
	}
	switch restParam.Kind {
	case restful.BodyParameterKind:
		ret.In = "body"
		ret.Schema, err = o.toSchema(restParam.DataType, nil)
		return ret, err
	case restful.PathParameterKind:
		ret.In = "path"
		if !restParam.Required {
			return ret, fmt.Errorf("path parameters should be marked at required for parameter %v", restParam)
		}
	case restful.QueryParameterKind:
		ret.In = "query"
	case restful.HeaderParameterKind:
		ret.In = "header"
	case restful.FormParameterKind:
		ret.In = "form"
	default:
		return ret, fmt.Errorf("unknown restful operation kind : %v", restParam.Kind)
	}
	openAPIType, openAPIFormat := common.GetOpenAPITypeFormat(restParam.DataType)
	if openAPIType == "" {
		return ret, fmt.Errorf("non-body Restful parameter type should be a simple type, but got : %v", restParam.DataType)
	}
	ret.Type = openAPIType
	ret.Format = openAPIFormat
	ret.UniqueItems = !restParam.AllowMultiple
	return ret, nil
}