My struct is not encoding correctly and is missing a property - go

type ApiResponse struct {
Success bool `json:"success"`
Errors []string `json:"errors"`
}
type NewSessionResponse struct {
ApiResponse `json:"apiResponse"`
authToken string `json:"authToken"`
}
In my handler I am doing this:
resp := NewSessionResponse{ApiResponse{true, []string{}}, "auth123"}
json.NewEncoder(w).Encode(resp)
The response I am seeing is this:
{
apiResponse: {
success: true,
errors: [ ]
}
}
Why isn't my authToken property in the JSON result?

authToken filed is an unexported field. Json library does not have the power to view fields using reflect unless they are exported. A package can only view the unexported fields of types within its own package.
You can export the filed to get this working
type NewSessionResponse struct {
ApiResponse `json:"apiResponse"`
AuthToken string `json:"authToken"`
}
FYI: Exported identifiers https://golang.org/ref/spec#Exported_identifiers

Related

Echo golang - issue with Swagger example values

I have ECHO server on GO and assigned on it Swagger.
If I'm using the structure which is on the same package (file) then example values are working well, ex:
type Test struct {
TestField string `json:"test_field" example:"testfield"`
type MaintenanceConfigPage struct {
ConfigFile string `json:"config_file" example:"configfile"`
Test TestField `json:"test"`
}
// maintenance godoc
// #Accept json
// #Produce json
// #Param data body MaintenanceConfigPage true "Config configuration"
// #Success 200 {object} string
// #Failure 400 {object} string
// #Router /maintenance [post]
func maintenanceSetupPost(echo_context echo.Context) error {
return echo_context.JSON(http.StatusOK, "test")
}
So, that on Swagger example value I'm getting correct value:
{ "config_file": "configfile", "test": {
"test_field": "testfield" } }
But issue is coming when I'm trying to import the struct from another package, like:
type MaintenanceConfigPage struct {
ConfigFile string `json:"config_file" example:"configfile"`
Test anotherPackage.TestField `json:"test"`
}
The everything is working, but swagger on example value providing just a
{}
If someone also receive before such problems and found the solution, please share

How to create graphql-go *graphql.Schema from JavaScript string?

How to create graphql schema from string in Go?
This is my schema, here shown as a JavaScript string:
const schemaContent = `type Query {
greeting:String
students:[Student]
}
type Student {
id:ID!
firstName:String
lastName:String
password:String
collegeId:String
}`
How can I build from the schemaContent string a scheme of type schema *graphql.Schema in Go?

Passing nested JSON as variable in Machinebox GraphQL mutation using golang

Hi there Golang experts,
I am using the Machinebox "github.com/machinebox/graphql" library in golang as client for my GraphQL server.
Mutations with single layer JSON variables work just fine
I am, however, at a loss as to how to pass a nested JSON as a variable
With a single layer JSON I simply create a map[string]string type and pass into the Var method. This in turn populates my graphql $data variable
The machinebox (graphql.Request).Var method takes an empty interface{} as value so the map[string]string works fine. But embedded json simply throws an error.
code:
func Mutate(data map[string]string, mutation string) interface{} {
client := GQLClient()
graphqlRequest := graphql.NewRequest(mutation)
graphqlRequest.Var("data", data)
var graphqlResponse interface{}
if err := client.Run(context.Background(), graphqlRequest, &graphqlResponse); err != nil {
panic(err)
}
return graphqlResponse
}
Mutation:
mutation createWfLog($data: WfLogCreateInput)
{
createWfLog (data: $data){
taskGUID {
id
status
notes
}
event
log
createdBy
}
}
data variable shape:
{
"data": {
"event": "Task Create",
"taskGUID": {
"connect": {"id": "606f46cdbbe767001a3b4707"}
},
"log": "my log and information",
"createdBy": "calvin cheng"
}
}
As mentioned, the embedded json (value of taskGUID) presents the problem. If value was simple string type, it's not an issue.
Have tried using a struct to define every nesting, passed in struct.
Have tried unmarshaling a struct to json. Same error.
Any help appreciated
Calvin
I have figured it out... and it is a case of my noobness with Golang.
I didn't need to do all this conversion of data or any such crazy type conversions. For some reason I got in my head everything HAD to be a map for the machinebox Var(key, value) to work
thanks to xarantolus's referenced site I was able to construct a proper strut. I populated the strut with my variable data (which was a nested json) and the mutation ran perfectly!
thanks!

Graphql object ( or JSON) as filter argument

Is it possible to have a JSON object as filed in filter arguments. Something like:
Query{
building(location:{lon,lat}){
name,...
}
}
I need to pass location, and I would like to pass it as js object ( to apollo client) or as stringified JSON.
You can use input types to achieve that. You need to edit your schema
type Query {
building(location: Location): Building
}
input Location {
lon: String
lat: String
}
Then you can post your query like this
query {
building(location: {lon:"100.332680",lat:"5.416393"}) {
name,...
}
}

Determine if POST data value matches struct field type

Using the gin framework I am trying to determine if POST'ed data does not match the struct field type and inform API user of their error.
type CreateApp struct {
LearnMoreImage string `db:"learn_more_image" json:"learn_more_image,omitempty" valid:"string,omitempty"`
ApiVersion int64 `db:"api_version" json:"api_version" valid:"int,omitempty"`
}
...
func CreateApps(c *gin.Context) {
var json models.CreateApp
c.Bind(&json)
So when I POST
curl -H "Content-Type: application/json" -d '{"learn_more_image":"someimage.jpg","api_version":"somestring"}' "http://127.0.0.1:8080/v1.0/apps"
I would like to determine whether the POST'ed data for field 'api_version' (passed as string) does not match the struct field it is being binded to (int). If the data doesnt match I'd like to send a message back to the user. Its for this reason I was hoping I could loop through the gin contexts data and check it.
The gin function 'c.Bind()' seems to omit invalid data and all subsequent data fields with it.
Gin has a built-in validation engine: https://github.com/bluesuncorp/validator/blob/v5/baked_in.go
but you can use your own or disable it completely.
The validator does not validate the wire data (json string), instead it validates the binded struct:
LearnMoreImage string `db:"learn_more_image" json:"learn_more_image,omitempty" binding:"required"`
ApiVersion int64 `db:"api_version" json:"api_version" binding:"required,min=1"`
Notice this: binding:"required,min=1"
Then:
err := c.Bind(&json)
or use a middleware and read c.Errors.
UPDATED:
Three workarounds:
Validate the json string your own (it can not be done with enconding/json)
Validate if integer is > 0 binding:"min=1"
Use a map[string]interface{} instead of a Struct, then validate the type.
func endpoint(c *gin.Context) {
var json map[string]interface{}
c.Bind(&json)
struct, ok := validateCreateApp(json)
if ok { /** DO SOMETHING */ }
}
func validateCreateApp(json map[string]interface{}) (CreateApp, bool) {
learn_more_image, ok := json["learn_more_image"].(string)
if !ok {
return CreateApp{}, false
}
api_version, ok = json["api_version"].(int)
if !ok {
return CreateApp{}, false
}
return CreateApp{
learn_more_image, api_version,
}
}

Resources