Displaying PUT body format with go-restful and swagger - go

I am using go-restful and swagger to generate apidocs which is working great. The problem I am facing is that when I add a body parameter to the documentation I would like to specify the DataType and its format. I can specify the DataType (i.e. UserFields), but the format of the JSON does not show in the Swagger UI, which can be very convenient.
Here is an example of what I am talking about:
The following link shows a body parameter and the corresponding JSON/model next to it http://petstore.swagger.wordnik.com/#!/store/placeOrder
In my case, the JSON/model is missing and only the DataType is displayed http://ibounce.co:8282/apidocs/#!/users/PutUserField
Here is the sample Go code is generates the documentation for this specific endpoint.
ws.Route(ws.PUT("/{id}/fields").
To(PutUserField).
Doc("Update user fields").
Operation("PutUserField").
Param(ws.HeaderParameter("Authorization", "username and password").DataType("string")).
Param(ws.PathParameter("id", "identifier of the user").DataType("int")).
Param(ws.BodyParameter("body", "identifier of the user").DataType("UserFields")).
Returns(http.StatusOK, http.StatusText(http.StatusOK), User{}).
Returns(http.StatusUnauthorized, http.StatusText(http.StatusUnauthorized), ApiError{}).
Returns(http.StatusBadRequest, http.StatusText(http.StatusBadRequest), ApiError{}))
UserFields is a struct:
type UserFields struct {
Email string `json:"email,omitempty"`
Phone string `json:"phone,omitempty"`
URL string `json:"url,omitempty"`
Address string `json:"address,omitempty"`
}
Any suggestions will be appreciated.

I figured it out. In the Go code above instead of
DataType("UserFields")
I have to use
DataType("main.UserFields")

Related

Pass input variable to output

Is it possible to pass an input variable to the output? I tried something like
this:
query GetUrlTitleDetails(
$geo: Country!
$platform: Platform! = WEB
) {
offers(country: $geo, platform: $platform) {
country
standardWebURL
}
}
but I get this result:
{"message": "Cannot query field \"country\" on type \"Offer\"."}
What are you trying to accomplish here? This is not possible (at least just using a GraphQL document).
Your outputs are defined by the GraphQL server. Not the client. Of course the output is derived using the inputs, but you just can't directly set outputs from your request. To do this, you have to change your GraphQL server.
Your code sample just shows your GraphQL document, which is simply the client request. If you want to pass the input variable to the output, you have to write the GraphQL service to pass the input to the output.
If I really want to do this, I'd do something like this (using Ballerina since I am more familiar with it).
import ballerina/graphql;
service on new graphql:Listener(9090) {
resource function get offers(string country, string platform) returns Offer {
return {
country: country,
standardWebURL: "<URL>"
};
}
}
type Offer record {|
string country;
string standardWebURL;
|};
Running this service, you can get the input country as part of the output, from your provided document.

Go omitempty bool field- not showing false type

I have a struct
type Settings struct {
Status bool `json:"status,omitempty"`
AvailableStatus bool `json:"available_status,omitempty"`
}
I am using this struct for saving the data and displaying the data in my GOAPis
for eg if for my save data my json body is like this
{"settings":{"status":true,
"available_status":false}}
after save I fetch data data using Get-API I am getting like this
"settings": {
"status": true
}
only true data is displaying I need to display both data and need to set omitempty also(omit empty for saving, after that json created and using json I am checking validation)
How can I do this?
for saving the data, all fields are not required.
I might be able to give json like below in my apis body.
{"settings":{"status":true,
"available_status":false}}
or
{"settings":{"status":true}}
I want to do this also. I created json for each model and validation is checking in json .. If I not added omitempty field it will show error available_status is required.
Or any other method for setting available_status as required filed..
"omitempty" is omitting only when value is equal to zerovalue of chosen type. If you want to create custom json from struct you can make map from struct and use json.Marshal or other lib like https://github.com/tidwall/sjson
Use pointers
type Settings struct {
Status *bool `json:"status,omitempty"`
AvailableStatus *bool `json:"available_status,omitempty"`
}

Do struct tags throw error to the API user?

type Person struct {
Id string
Roll_no int
Email string `json:"email" validate:"required"`
}
The email here is required. If the user does not provide that in the request body of the API call, will Go handle the name validation automatically and throw the error if this field is not provided? Or would i neeI to validate it manually in my code and throw the error in some form of a http status code?
Do struct tags throw error to the API user?
No. For a lot of reasons.
Some struct tags (e.g. the json ones) are just used by package encoding/json to map between JSON object elements and struct fields).
Other struct tags (like validate) are used by certain 3rd party packages and if you do not use that package nothing at all will happen.
Go (the language and its stdlib) is "free from magic". Nothing magically happens. If you need validation on your API endpoints you might use validation packages which inspect struct tags but this won't happen magically: You have to call these functions and return an API error yourself. And no, I won't recommend a framework here.
To work struct tags have to be valid, none of yours are. Run go vet to find this type of problem. (should be json:"emal" validate:"required" and probably even "email")
Errors in Go are not "thrown" at all. Especially HTTP responses with a status code of 400 Bad Request are not "thrown". It always helps to get the terminology correct).
If the JSON sent over API does not contain Email then encoding/json json.Unmarshal will treat it as if Email was an empty string.
Option A: If empty string is not a valid Email, you can check for an empty string after json.Unmarshal
var person Person
err := json.Unmarshal(jsonBlob, &person)
if err != nil{
return err
}
if person.Email == "" {
return errors.New("email cannon be empty"
}
Option B: If empty string is valid, you can create a custom MarshalJSON to parse JSON as a string and look for the Email key.
https://pkg.go.dev/encoding/json#example-package-CustomMarshalJSON

How to make fields in QoR model readonly?

I have a data model:
type Epg struct {
gorm.Model
Uri string `gorm:";not null;unique"`
Prefix string `gorm:"size:64;not null;default:''"`
Etag string
Updated time.Time
Status bool `gorm:"default:true"`
}
I publish this data model in menu:
EpgResource := Admin.AddResource(&models.Epg{}, &admin.Config{Menu: []string{"Content"}})
Now I can view and edit data via QoR Admin panel. But I want to make values Etag, Updated, Status to be readonly because they are updated by the system.
If I try to make this fields readonly according documentation:
EpgResource.Meta(&admin.Meta{Name: "Etag", Type: "Readonly"})
I got an error. Is it possible to make some fields in data model visible but readonly? How to do that?
Error log trace.
2017/04/25 01:16:04 Finish [GET] /admin/epgs Took 19.59ms
/usr/local/go/src/text/template/exec.go:433
/usr/local/go/src/text/template/exec.go:536
/usr/local/go/src/text/template/exec.go:668
/usr/local/go/src/reflect/value.go:302
/usr/local/go/src/reflect/value.go:434
/usr/local/go/src/runtime/asm_amd64.s:515
/home/rns/golang/src/github.com/qor/admin/func_map.go:1051
/home/rns/golang/src/github.com/qor/admin/func_map.go:220
/home/rns/golang/src/github.com/qor/admin/func_map.go:236
/home/rns/golang/src/github.com/qor/admin/func_map.go:393
got error when render form template for Etag(Readonly): haven't found form
template for meta Etag
That particular error is being caused by qor not finding a template file at .../metas/form/Etag.tmpl, which is presumably needed to actually render the Etag to the form. (You can make the template render a readonly/static element rather than an input)
EpgResource.Meta(&admin.Meta{Name: "Etag", Type: "Readonly"}) would work only on darwin (Mac) machines. But, not on linux machines.
Do the following:
EpgResource.Meta(&admin.Meta{Name: "Etag", Type: "readonly"})
I hope this helps.
Reference: https://doc.getqor.com/admin/metas/hidden-readonly.html#readonly

What is the best way to notify api clients of null-valued properties of returned JSON object?

I have an asp.net web api 2 application that provides data in JSON format for api clients. For GET api methods, an api client programmer who is using Java and C++ languages to call those GET method apis. However, for null-valued properties of JSON objects, the client programmer says he receives "null" (null in-quote string) for those properties. In SQL Server database for nvarchar (string) and datetime columns of different database tables, I save those null-valued columns as null as normal SQL server convention but not "null" string.
My question is what is the best way to let api client programmers know if a null-valued property is null to distinguish it from real "null" string, e.g. {"state": "null"} a literal string. Thanks in advance.
I have many GET method apis which returns null for null-valued properties of JSON objects.
I test my GET Api methods for null properties with Postman or Advanced Rest Client tool, I do not see those tool returns null in "null" (in-quote string) for null-valued properties: (here is state and closeddate properties)
{"firstname":"abc","lastname":"def","state":null,"birthdate":"1992-05-25T00:00:00","closeddate":null}
One of GET method api looks like:
[HttpGet]
public HttpResponseMessage GetUserInfo(int userid)
{
var user = _userService.GetUserInfo(userid);
var statusCode = _userService.StatusCode;
var errorCode = _userService.ErrorCode;
return _statusCode == HttpStatusCode.OK
? Request.CreateResponse(_statusCode, account)
: Request.CreateResponse(_statusCode, errorCode);
}
Since you are asking for an opinion, here's one from the creator of SlashDB API: when in doubt, leave it out.
In the JSON data format keys with null value can be omitted from the result.
The following API call returns a Customer record, which does not have a value in the Company field:
HTML rendering: http://demo.slashdb.com/db/Chinook/Customer/CustomerId/2.html
JSON rendering: http://demo.slashdb.com/db/Chinook/Customer/CustomerId/2.json
XML format is more formal about it because you can define a schema, which prescribes what is the allowed shape of data. In particular, an element (tag) could have a minOccurs=0 attribute to indicate its optionality, and/or a nillable=True to indicate that a tag could be present without a value (i.e. ). For completeness here's the same record in XML and its schema:
XML rendering: http://demo.slashdb.com/db/Chinook/Customer/CustomerId/2.html
XSD schema: http://demo.slashdb.com/db/Chinook/Customer.xsd

Resources