Why not all key from Revel JSON response are capitalized? - go

I'm trying to understand how to implement POST request using Revel framework.
models/login.go
package models
type LoginParam struct {
Username string `form:"username" json:"username"`
Password string `form:"password" json:"password"`
}
type Response struct {
Message string `json:"message`
Data string `json:"data"`
}
app/controllers/login.go
package controllers
import (
"mytestapi/app/models"
"encoding/json"
"log"
"strconv"
"github.com/revel/revel"
)
type Login struct {
*revel.Controller
}
func (c Login) DoLogin() revel.Result {
var login models.LoginParam
var res models.Response
err := json.NewDecoder(c.Request.GetBody()).Decode(&login)
if err != nil {
log.Fatal("JSON decode error: ", err)
}
res.Message = "OK"
res.Data = login.Username + " " + login.Password
defer c.Request.Destroy()
return c.RenderJSON(res)
}
Postman gives this output:
{ "Message": "OK", "data": "foo barzzzz" }
Almost correct. On the JSON output, Message instead of message is printed.
Why Message is capitalized, and data is not?

You are missing a double quote after the tag message:
type Response struct {
Message string `json:"message`
Data string `json:"data"`
}

Related

Validation in GO "ozzo-validation"

I'm nob in GO :) just try to create simple crud throw it using gin and plugin called ozzo-validation
My code:
package models
import (
validation "github.com/go-ozzo/ozzo-validation"
"gorm.io/gorm"
)
type Post struct {
gorm.Model
Name string `gorm:"type:varchar(255);"`
Desc string `gorm:"type:varchar(500);"`
}
type PostData struct {
Name string `json:"name"`
Desc string `json:"desc"`
}
func (p PostData) Validate() error {
return validation.ValidateStruct(&p,
validation.Field(&p.Name, validation.Required, validation.Length(5, 20)),
validation.Field(&p.Desc, validation.Required),
)
}
PostController:
package controllers
import (
"curd/app/models"
"fmt"
"github.com/gin-gonic/gin"
)
func Store(c *gin.Context) {
// Validate Input
var post models.PostData
err := post.Validate()
fmt.Println(err)
}
{
"name": "sdfsdfsfsdf"
}
The problem is once I submit the above JSON data from the postman the validation gives me this in terminal :
desc: cannot be blank; name: cannot be blank.
As noted in the comments, you need to decode the data from the HTTP request into the struct before you can perform validation. The validation errors you're seeing are a product of calling Validate() on a fresh instance (with zero values in every field) of your Post struct. Try this.
func Store(c *gin.Context) {
var post models.PostData
// This will infer what binder to use depending on the content-type header.
if err := c.ShouldBind(&post); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// Validate Input
err := post.Validate()
fmt.Println(err)
}

Correct request body is deemed to be invalid by validator in Go

I am trying to validate the request body according to this struct using validator. But in Postman it always throws an error when validating the struct. I just want all values to be required when making a request.
package model
type User struct {
FeatureName string `json:"featureName" validate:"required"`
Email string `json:"email" validate:"required"`
CanAccess *bool `json:"can_access" validate:"required"`
}
I have tried sending this as the request body on Postman:
// Request body
{
"featureName": "crypto",
"email": "test5#gmail.com",
"can_access": true
}
// Response body
{
"status": 422,
"message": "Missing parameters featureName/can_access/email"
}
Code:
package controller
import (
"database/sql"
"encoding/json"
"errors"
"net/http"
"unicode/utf8"
"github.com/yudhiesh/api/model"
"gopkg.in/validator.v2"
"github.com/yudhiesh/api/config"
)
func InsertFeature(w http.ResponseWriter, r *http.Request) {
var user model.User
var response model.Response
db := config.Connect()
defer db.Close()
// Decode body into user struct
if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
response.Message = "Error"
response.Status = http.StatusInternalServerError
json.NewEncoder(w).Encode(response)
return
} else {
// Validate struct to check if all fields are correct
// Fails here!
if err := validator.Validate(user); err != nil {
response.Message = "Missing parameters featureName/can_access/email"
response.Status = http.StatusUnprocessableEntity
json.NewEncoder(w).Encode(response)
return
} else {
// Execute insert statement to database
stmt := `INSERT INTO features (user_id, feature_name, can_access) SELECT id, ?, ? FROM users WHERE email=?`
if _, err = db.Exec(stmt, &user.FeatureName, &user.CanAccess, &user.Email); err != nil {
response.Message = "Error"
response.Status = http.StatusInternalServerError
json.NewEncoder(w).Encode(response)
return
} else {
response.Message = "Success"
response.Status = http.StatusOK
json.NewEncoder(w).Encode(response)
return
}
}
}
}
Moving Comment to answer
I see a problem in your code the link you have shared is https://github.com/go-playground/validator but in the code, import is gopkg.in/validator.v2
If you are using the go-playground validator Use below code to validate
import https://github.com/go-playground/validator
validatorInstance:=validator.New()
validatorInstance.Struct(user)

failed get post request in golang

I have a problem how to get post request on Go.
I was trying json.Unmarshal() but its still not working
package controllers
import (
"encoding/json"
"net/http"
"github.com/gin-gonic/gin"
)
//CreateOrder function
func CreateOrder(c *gin.Context) {
var requestBody struct {
TransNo string `json:"trans_no"`
}
err := json.NewDecoder(c.Request.Body).Decode(&requestBody)
if err != nil {
panic(err)
}
c.JSON(http.StatusOK, gin.H{"data": requestBody.TransNo})
}
I no have any errors, but the result not showing anything.
this my post data:
{
"transaction_details": {
"trans_no": "12400099",
"gross_amount": 50000
}
}
I want to get trans_no value
Your requestBody struct would unmarshal correctly if your post data was:
{
"trans_no": "12400099",
"gross_amount": 50000
}
but since that information is nested one deeper, you need to include that nesting in your model.
var requestBody struct {
TransactionDetails struct {
TransNo string `json:"trans_no"`
} `json:"transaction_details"`
}

Consume a nested array inside JSON request in Go

How do I go about consuming the following json post in Go?
{
"notificationType": "email",
"client": "The CLient",
"content": "Hellow World",
"recipients": [
{
"address": "email1#example.com"
},
{
"address": "email2#example.com"
}
]
}
I've managed to get the string types but I really don't know enough about Go to deal with the recipients array.
My code looks like this:
package handlers
import (
"net/http"
"encoding/json"
"notificationservice/src/validation"
"io/ioutil"
"fmt"
)
func EmailHandler(w http.ResponseWriter, r *http.Request) {
b, err := ioutil.ReadAll(r.Body)
defer r.Body.Close()
if err != nil {
http.Error(w, err.Error(), 500)
return
}
var postData validation.EmailValidator
err = json.Unmarshal(b, &postData)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
fmt.Println(postData.Client)
fmt.Println(postData.Content)
}
My struct:
package validation
import "fmt"
type EmailValidator struct {
Client string `json:"client"`
Content string `json:"content"`
//Recipients []string `json:"recipients"`
}
func (validator * EmailValidator) ValidateEmail() (bool) {
var required = []string {validator.Client, validator.Content, validator.Stuff}
for _, param := range required {
fmt.Println(param)
}
return true;
}
I've tried setting Recipients to []string and [][]string but I really don't know what I'm doing.
In PHP I would use the var_dump command to print out the entire object and debug step by step from there, but Go doesn't appear to have that functionality.
You can try something like this:
package main
import (
"encoding/json"
"fmt"
)
type Email struct {
Adress string `json:"address"`
}
type EmailValidator struct {
Client string `json:"client"`
Content string `json:"content"`
Recipients []Email `json:"recipients"`
}
func main() {
j := `{
"notificationType": "email",
"client": "The CLient",
"content": "Hellow World",
"recipients": [
{
"address": "email1#example.com"
},
{
"address": "email2#example.com"
}
]
}`
result := EmailValidator{}
json.Unmarshal([]byte(j), &result)
fmt.Printf("%+v", result) // something like var_dump in PHP
}
You need an array of "things with an address":
type EmailValidator struct {
Client string `json:"client"`
Content string `json:"content"`
Recipients []Recipient `json:"recipients"`
}
type Recipient struct {
Address string `json:"address"`
}
You can nest objects, and Unmarshal will handle the entire tree for you.
type Recipient struct {
Address string `json:"address"`
}
type EmailValidator struct {
Client string `json:"client"`
Content string `json:"content"`
Recipients []Recipient `json:"recipients"`
}
The rest of your code looks good.

Recieving a EOF Panic error

I'm trying to decode a json I get. Here's an example json I get:
{"response":"1","number":"1234","id":nil}
Here's my struct:
type AutoGenerated struct {
Response string `json:"response"`
Number string `json:"number"`
ID interface{} `json:"id"`
}
I use the decode function in encode/json. What Am I getting wrong? ID has the chance to be both a string or a nil value.
Here's me exact error incase it helps.
panic: EOF
Without you showing how you're doing it, I think the best answer is to show you how to do it.
package main
import (
"fmt"
"log"
"encoding/json"
)
func main() {
j := []byte(`{"response":"1","number":"1234","id":null}`)
data := AutoGenerated{}
err := json.Unmarshal(j, &data)
if err != nil {
log.Println(err.Error())
return
}
fmt.Println(data)
}
type AutoGenerated struct {
Response string `json:"response"`
Number string `json:"number"`
ID interface{} `json:"id"`
}
The JSON string you put here is invalid. You can find this code sample for reference.
If you're going to set the id field to nil, just don't put it in the JSON string.
package main
import (
"encoding/json"
"fmt"
"io"
"log"
"strings"
)
type AutoGenerated struct {
Response string `json:"response"`
Number string `json:"number"`
ID interface{} `json:"id"`
}
func main() {
jsonStream := `
{ "response": "1", "number": "1234" }
{ "response": "1", "number": "1234", "id": "nil" }
`
decoder := json.NewDecoder(strings.NewReader(jsonStream))
for {
var m AutoGenerated
if err := decoder.Decode(&m); err == io.EOF {
break
} else if err != nil {
log.Fatal(err)
}
fmt.Println(m)
}
}
The output of the program is:
{1 1234 <nil>}
{1 1234 nil}

Resources