Swagger is not working with JSONAPI - Golang - go

Swagger is not creating example with expected format: How to use swagger with json-api golang
Input struct:
type example struct {
ID string `jsonapi:"primary,examples"`
value string `jsonapi:"attr,value"`
}
Expected format:
{
"data":[
{
"type": "examples",
"id": "01FDG693F2MS0ZCEW925MZ7BAA",
"attributes": {
"value": "xxx.xxx.xxx.xxx",
}
}
],
}

Related

How to Marshal/Unmarshal a common JSON & BSON key/field that can have two different formats in Go?

I currently have mongo data stored in two forms (specifically for content key) in a collection. Partial sample data shown below:
Format 1.
{
"type": "text",
"content": "foobar",
"extraTextData": "hello text"
}
Format 2
{
"type": "group",
"content": [
{
"type": "text",
"content": "grouped-foobar"
},
{
"type": "image",
"url": "https://abc.jpg"
},
],
"extraGroupData": "hello group"
}
My attempt to structure this in golang is below.
type C struct {
Type string `json:"type" bson:"type"`
Content ???
*TextC
*GroupC
}
type TextC struct {
ExtraTextData `json:"extraTextData" bson:"extraTextData"`
}
type GroupC struct {
ExtraGroupData `json:"extraGroupData" bson:"extraGroupData"`
}
I am having issues on how to setup the structure for "content" field that works for both the formats, TextC and GroupC.
Content for GroupC can be array of C like - Content []C
Content for TextC can also be string type.
Can someone please help & give an example on how to tackle this situation?
Format2 json is Invalid. You can check it here : https://jsonlint.com/
I have created a sample scenario for your case.
You can try it here: https://go.dev/play/p/jaUE3rjI-Ik
Use interface{} like this:
type AutoGenerated struct {
Type string `json:"type"`
Content interface{} `json:"content"`
ExtraTextData string `json:"extraTextData,omitempty"`
ExtraGroupData string `json:"extraGroupData,omitempty"`
}
And you should also remove comma from Format2:
{
"type": "group",
"content": [
{
"type": "text",
"content": "grouped-foobar"
},
{
"type": "image",
"url": "https://abc.jpg"
}
],
"extraGroupData": "hello group"
}
If you don't remove comma then it will through an error like this:
invalid character ']' looking for beginning of value

Golang struct to Json schema

Hi I need to infer a json schema (github.com/go-openapi/spec.Schema) from a struct :
type Testcase struct {
Id string `json:"id,omitempty"` // id of this test case
Name string `json:"name,omitempty"` // name of this test case
CreationDate time.Time `json:"creation_date,omitempty"` // timestamp when the scenario was first created
UpdateDate time.Time `json:"update_date,omitempty"` // last update timestamp
Steps []Step `json:"steps,omitempty"` // list of steps type:"[]StepCcs"
}
I can't find a simple way to do so.
I guess that this is a prerequisite for many REST frameworks out there that generate open api spec from the code.
Can someone point me out to a package that contains such helper : ie
func toSchema(obj interface{}) (spec.Schema, error)
https://github.com/invopop/jsonschema
is what you are looking for.
type TestUser struct {
ID int `json:"id"`
Name string `json:"name" jsonschema:"title=the name,description=The name of a friend,example=joe,example=lucy,default=alex"`
Friends []int `json:"friends,omitempty" jsonschema_description:"The list of IDs, omitted when empty"`
Tags map[string]interface{} `json:"tags,omitempty" jsonschema_extras:"a=b,foo=bar,foo=bar1"`
BirthDate time.Time `json:"birth_date,omitempty" jsonschema:"oneof_required=date"`
YearOfBirth string `json:"year_of_birth,omitempty" jsonschema:"oneof_required=year"`
Metadata interface{} `json:"metadata,omitempty" jsonschema:"oneof_type=string;array"`
FavColor string `json:"fav_color,omitempty" jsonschema:"enum=red,enum=green,enum=blue"`
}
Results in following JSON Schema:
jsonschema.Reflect(&TestUser{})
Huma's schema package can do this. Be sure to check out all the validation tags that are available. Example:
import "github.com/danielgtaylor/huma/schema"
// First define some structs:
type Child struct {
Name string `json:"name" doc:"Child name"`
}
type Hello struct {
Greeting string `json:"greeting" maxLength:"80" doc:"A greeting message"`
Optional uint `json:"optional,omitempty" doc:"Optional integer example"`
Child *Child `json:"child,omitempty" doc:"Child struct example"`
Labels []string `json:"labels" maxItems:"10" doc:"Array example"`
Created time.Time `json:"created" doc:"Created time for this greeting"`
}
// Then later you can do:
s, err := schema.Generate(reflect.TypeOf(Hello{}))
https://go.dev/play/p/4F8NpcgZ4Yh
This will output:
{
"type": "object",
"properties": {
"child": {
"type": "object",
"description": "Child struct example",
"properties": {
"name": {
"type": "string",
"description": "Child name"
}
},
"additionalProperties": false,
"required": [
"name"
]
},
"created": {
"type": "string",
"description": "Created time for this greeting",
"format": "date-time"
},
"greeting": {
"type": "string",
"description": "A greeting message",
"maxLength": 80
},
"labels": {
"type": "array",
"description": "Array example",
"items": {
"type": "string"
},
"maxItems": 10
},
"optional": {
"type": "integer",
"description": "Optional integer example",
"format": "int32",
"minimum": 0
}
},
"additionalProperties": false,
"required": [
"greeting",
"labels",
"created"
]
}

go-restful-openapi $refs must reference a valid location in the document

I'm using go-restful in combination with go-restful-openapi to generate my swagger doc automatically. However, on testing the tool with the swagger-editor, I get the following error:
$refs must reference a valid location in the document
struct
type Users struct {
# uuid imported from github.com/google/uuid#v1.2.0
RelatedUsers []uuid.UUID `json:"relatedIds" validate:"required"`
}
generated swagger snippet
"Users": {
"required": [
"relatedIds"
],
"properties": {
"relatedIds": {
"type": "array",
"$ref": "#/definitions/uuid.UUID" #this line returns an error
}
}
}
}
Here's the swagger config:
swaggerConfig := restfulspec.Config{
WebServices: restfulContainer.RegisteredWebServices(),
APIPath: "/swagger.json",
PostBuildSwaggerObjectHandler: func(swo *spec.Swagger) {
swo.Info = &spec.Info{
InfoProps: spec.InfoProps{
Title: "User Service",
Description: "An example service for stackoverflow",
Version: "1.0.0",
},
}
},
}
NOTE: If I replace the lines above in the swagger editor as follows the error disappears, however, I couldn't figure out how to configure swagger to do so automatically
"Users": {
"required": [
"relatedIds"
],
"properties": {
"relatedUsers": {
type: array
items:
type: "string"
format: "uuid"
}
}
}
}
Just in case someone is running into this issue: go-restful-openapi cannot resolve imported custom types. To solve this issue add the type to the definitions
swo.Definitions["uuid.UUID"] = spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "uuid",
},
}

How to filter on a array with graphql in Generic Mesh CMS?

Im trying to get just entrys which have in a specific value in a array (myArray: [String]).
Displaying of this Array is not Problem:
query ($lang: [String!], $filter: String!) {
nodes(lang: $lang, filter: {schema: {is: myObj}, fields: {myObj: {name: {regex: $filter}}}}) {
elements {
uuid
language
availableLanguages
fields {
... on module {
name
myArray
}
}
node {
language
fields {
... on module {
name
myArray
}
}
}
}
}
}
Result:
{
"data": {
"nodes": {
"elements": [
{
"uuid": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
"language": "de",
"availableLanguages": [
"de"
],
"fields": {
"name": "ASDF",
"myArray": [
"CAT_1",
"CAT_2"
]
},
"node": null
}
]
}
}
}
How can I filter on myArray? That I just et elements with the value uf $filter in the array myArray?
In the GraphiQL I can't find the myArray in the docs under the filter - fields.
GraphQL-Filtering for list types is not supported yet. In the GraphiQL docs you will only find supported fields for now.
See supported field types here: https://getmesh.io/docs/beta/graphql.html#_filtering_limitations
Here is the open issue on Github regarding this feature: https://github.com/gentics/mesh/issues/27

Confusion creating swagger.json file from proto file

I've created a proto file with all the necessary messages and rpc functions for a REST webservice I intend to generate. Using the protoc-gen-swagger plugin I've managed to compile that proto file into a swagger.json file and all seems well, except for two things, which I can't seem to work out.
All the definitions in the swagger.json file has the name of my proto file's package prefixed onto them. Is there a way to get rid of this?
All of the fields of my messages are "optional". They're not specified explicitly as such but they're not specified to be "required" which, by definition, makes them optional. Proto3 no longer supports required/optional/repeating but even if I use Proto2 and add those keywords, it doesn't seem to affect the swagger.json ouput. How do I specifiy in my proto file that a field is required such that protoc-gen-swagger will add the required section to the json output?
Here is a sample of a very basic proto file:
webservice.proto
syntax = "proto3";
package mypackage;
import "google/api/annotations.proto";
service MyAPIWebService {
rpc MyFunc (MyMessage) returns (MyResponse) {
option (google.api.http) = {
post: "/message"
body: "*"
};
}
}
message MyMessage {
string MyString = 1;
int64 MyInt = 2;
}
message MyResponse {
string MyString = 1;
}
This is then compiled into a swagger.json file with the following command:
protoc -I. -I"%GOPATH%/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis" --swagger_out=logtostderr=true:. webservice.proto
which yields the following output:
webservice.swagger.json
{
"swagger": "2.0",
"info": {
"title": "webservice.proto",
"version": "version not set"
},
"schemes": [
"http",
"https"
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"paths": {
"/message": {
"post": {
"operationId": "MyFunc",
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/mypackageMyResponse"
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/mypackageMyMessage"
}
}
],
"tags": [
"MyAPIWebService"
]
}
}
},
"definitions": {
"mypackageMyMessage": {
"type": "object",
"properties": {
"MyString": {
"type": "string"
},
"MyInt": {
"type": "string",
"format": "int64"
}
}
},
"mypackageMyResponse": {
"type": "object",
"properties": {
"MyString": {
"type": "string"
}
}
}
}
}
Notice how MyMessage and MyResponse in the proto file translates to mypackageMyMessage and mypackageMyResponse in the json file.
If I wanted, for instance, MyMessage:MyString to be required, I'd have to add a section to the "mypackageMyMessage" section in "definitions" that looks like this:
"required":[
"MyString"
]
I would definitely prefer if there was a way I could specify that in the proto file already so that I don't have to manually edit the json file every time I compile it.
Posting here for anyone else who comes across this question looking for the same information.
UPDATE
This is where the code defines how definitions are created.
https://github.com/grpc-ecosystem/grpc-gateway/blob/master/protoc-gen-swagger/genswagger/template.go#L859
This is how you can denote fields as required -- add a custom option to your message definition:
message MyMessage {
option (grpc.gateway.protoc_gen_swagger.options.openapiv2_schema) = {
json_schema: {
title: "MyMessage"
description: "Does something neat"
required: ["MyString"]
}
};
string MyString = 1;
int64 MyInt = 2;
}
Your prefix mypackage is a part of namespacing in .proto file. It is coming from line: package mypackage; delete this line and regenerate json

Resources