json marshal araylist in golang - json

Hi there I back to ask again
sorry if you guys think I lack of searching but been doing this for hours and I still don't get it why
I have a controller like this in Golang :
c3 := router.CreateNewControllerInstance("index", "/v4")
c3.Post("/insertEmployee", insertEmployee)
and using Postman to throw this arraylist request , the request is like this
[{
"IDEmployee": "EMP4570787",
"IDBranch": "ALMST",
"IDJob": "PRG",
"name": "Mikey Ivanyushin",
"street": "1 Bashford Point",
"phone": "9745288064",
"join_date": "2008-09-18",
"status": "fulltime"
},{
"IDEmployee": "EMP4570787",
"IDBranch": "ALMST",
"IDJob": "PRG",
"name": "Mikey Ivanyushin",
"street": "1 Bashford Point",
"phone": "9745288064",
"join_date": "2008-09-18",
"status": "fulltime"
}]
and also I have 2 Struct like this
type EmployeeRequest struct {
IDEmployee string `json: "id_employee"`
IDBranch string `json: "id_branch" `
IDJob string `json: "id_job" `
Name string `json: "name" `
Street string `json: "street" `
Phone string `json: "phone" `
JoinDate string `json: "join_date" `
Status string `json: "status" `
Enabled int `json: "enabled" `
Deleted int `json: "deletedstring"`
}
type ListEmployeeRequest struct {
ListEmployee []EmployeeRequest `json: "request"`
}
for some reason the problem start here , when I try to run my function to read the json that I send from Postman
here is the function that I try to run
func insertEmployee(ctx context.Context) {
tempReq := services.ListEmployeeRequest{}
temp1 := ctx.ReadJSON(&tempReq.ListEmployee)
var err error
if err = ctx.ReadJSON(temp1); config.FancyHandleError(err) {
fmt.Println("err readjson ", err.Error())
}
parsing, errParsing := json.Marshal(temp1)
fmt.Println("", string(parsing))
fmt.Print("", errParsing)
}
the problem occur on the line if err = ctx.ReadJSON(temp1); config.FancyHandleError(err)
it tell me that I got unexpected end of JSON input am I doing something wrong there when I throw the request from Postman? or I made a wrong validation code?
can someone tell me what to do next for me to be able to read the JSON that I throw from postman?
thanks for your attention and help , much love <3

You have multiple issues here:
Tag names don't match the JSON input, e.g. id_employee vs IDEmployee.
Your tag syntax is not correct, it shows when you run go vet, it should be json:"id_employee"
You don't need another List struct, if you use it your json should be {"requests":[...]}. Instead you can deserialize a slice:
var requests []EmployeeRequest
if err := json.Unmarshal([]byte(j), &requests); err != nil {
log.Fatal(err)
}
You can see a running version here: https://play.golang.org/p/HuycpNxE6k8

type EmployeeRequest struct {
IDEmployee string `json:"IDEmployee"`
IDBranch string `json:"IDBranch"`
IDJob string `json:"IDJob"`
Name string `json:"name"`
Street string `json:"street"`
Phone string `json:"phone"`
JoinDate string `json:"join_date"`
Status string `json:"status"`
Enabled int `json:"enabled"`
Deleted int `json:"deletedstring"`
}
some of json tags didn't match with fields.

Related

golang how i can get value from []interface {} type

i have var (name result["error_type"]) with type
[]interface {}
and value
[map[reason:map[phone:empty] send_at:1.636697291e+09 status:error]]
how i cat get value from type []interface {}
example result["error_type"]["128"]["reason"]["phone"]
this type i got from
var result map[string]interface{}
json.NewDecoder(r.Body).Decode(&result)
r.Body has Json
{
"offer_name":"EbcBankruptcy",
"offer_id":"288",
"partner_name":"середов",
"partner_id":"1",
"type_system":"gb",
"status":"success",
"date_request":"2021-01-02 11:03",
"bank_name":"alfa",
"bank_id":"1",
"type_product":"1",
"error_type":{"128": [{"reason": {"phone": "Отсутствует обязательное поле номер телефона"}, "status": "error", "send_at": 1636697291}], "200": [{"reason": {"phone": "Отсутствует обязательное поле номер телефона"}, "status": "error", "send_at": 1636697281}]},
"request_id":"1"
}
also i dont create structure error_type for json.NewDecoder parse because i dont know what kind id will be in error_type in json (128, 200, 300)
i try get value
test["reason"]["phone"]
but, its not work
also cast to
map[string]interface{}
its not work
As far as the understanding from the question, what I understand is you can format the data as following.
type Payload struct {
OfferName string `json:"offer_name"`
OfferID string `json:"offer_id"`
PartnerName string `json:"partner_name"`
PartnerID string `json:"partner_id"`
TypeSystem string `json:"type_system"`
Status string `json:"status"`
DateRequest string `json:"date_request"`
BankName string `json:"bank_name"`
BankID string `json:"bank_id"`
TypeProduct string `json:"type_product"`
// you can use the type map of array of error data here
ErrorType map[string][]ErrorData `json:"error_type"`
RequestID string `json:"request_id"`
}
type ErrorData struct {
Reason Reason `json:"reason"`
Status string `json:"status"`
SendAt int `json:"send_at"`
}
type Reason struct {
Phone string `json:"phone"`
}
With the following you can unmarshal the data to
fmt.Printf("%+v", p.ErrorType["128"][0].Reason)
In the case you are unable to know the keys of the map, you can still range over the map values and get the data.
Here is the playground link https://go.dev/play/p/oTF0JUwOj0D

Empty fields while unmarshalling depending on type

I have the following structs:
type Company struct {
Id uuid.UUID `json:"id"`
Name string `json:"name"`
Presentation string `json:"presentation"`
Jobs []*Job `json:"jobs"`
}
type Job struct {
Id uuid.UUID `json:"id"`
Title string `json:"title"`
Description string `json:"description"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
When trying to unmarshal a json string that should match this struct hierarchy, some fields are filled in and others not. Mainly the uuid, but I also manage to get the title filled in the Jobs but not the description:
func main() {
s := `{"id": "2cc588a8-087a-4b81-a17f-3c9c35d2e958", "jobs": [{"id": "e1498403-82d8-47a9-b744-96b00c8b91e6", "title": "Qsd", "created_at": "2020-09-07T22:52:22.376857", "updated_at": "2020-09-07T22:52:22.376857", "description": "<p>sd</p>\n"}], "name": "NC", "presentation": "<p>qsdq</p>\n"}`
var company *Company
json.Unmarshal([]byte(s), &company)
log.Printf("%+v\n", company)
log.Printf("%+v\n", company.Jobs[0])
}
I'm not too surprised with the dates requiring a bit more formating but I don't get the inconsistencies on string fields. I have set up the code in the playground so everyone can test for themselves here.
The only real issue is that you are ignoring the error returned from json.Unmrshal. Because you are getting an error, you can't really rely on &company - it basically just gave up on it once it ran into an invalid date field, otherwise Description would have been fine:
https://play.golang.org/p/pxnIlmlPCq5

Custom JSON struct Unmarshal

I'm using an API that returns the result as the name of the object and I am trying to unmarshal just the fields of the struct. Here is an example of the JSON:
{
"AAPL": {
"symbol": "AAPL",
"description": "Apple Inc. - Common Stock",
"lastPrice": 284.45,
"openPrice": 284.69,
"highPrice": 284.89,
"lowPrice": 282.9197,
}
}
You can see it is using "AAPL" as the name of the struct and I'm not sure how to unmarshal it. I'm looking to unmarshal into this struct:
type Quote struct {
Symbol string `json:"symbol"`
Description string `json:"description"`
LastPrice float64 `json:"lastPrice"`
OpenPrice int `json:"openPrice"`
HighPrice int `json:"highPrice"`
LowPrice int `json:"lowPrice"`
}
I assume I need to write a custom unmarshal func
func (q *Quote) UnmarshalJSON(b []byte) error {
...
}
I'm not sure of the contents. Any assistance is appreciated!
I think you are looking for json:"-".
https://golang.org/pkg/encoding/json/#Marshal
As a special case, if the field tag is "-", the field is always omitted. Note that a field with name "-" can still be generated using the tag "-,".

Write specific JSON fields to file

I've just started studying Golang and don't understand how to write only specific JSON fields to an output file.
For example I have this struct:
type example struct {
Ifindex int `json:"ifindex"`
HostID int `json:"host_id"`
Hostname string `json:"hostname"`
Name string `json:"name"`
}
My output file should be in the following format:
[{"Ifindex": int, "Hostname": string}, {...}]
How can I do it?
If I understood correctly, you'd like to omit some of the fields when marshalling to JSON. Then use json:"-" as a field tag.
Per the json.Marshal(...) documentation:
As a special case, if the field tag is "-", the field is always omitted.
So you just need to use the tag "-" for any public field that you do not want serialized, for example (Go Playground):
type Example struct {
Ifindex int `json:"ifindex"`
HostID int `json:"-"`
Hostname string `json:"hostname"`
Name string `json:"-"`
}
func main() {
eg := Example{Ifindex: 1, HostID: 2, Hostname: "foo", Name: "bar"}
bs, err := json.Marshal(&eg)
if err != nil {
panic(err)
}
fmt.Println(string(bs))
// {"ifindex":1,"hostname":"foo"}
}

Creating struct to read from API in Go

I'm working on a project and it is my first time using Go.
The project queries a number of APIs and for the most part I have had no trouble getting this working.
Coming from a PHP background, creating Go type definitions for my JSON responses is a little different.
I am stuck on one API, a Magento API, that returns a JSON response like so:
{
"66937": {
"entity_id": "66937",
"website_id": "1",
"email": "email#email.com",
"group_id": "1",
"created_at": "2017-08-11 02:09:18",
"disable_auto_group_change": "0",
"firstname": "Joe",
"lastname": "Bloggs",
"created_in": "New Zealand Store View"
},
"66938": {
"entity_id": "66938",
"website_id": "1",
"email": "email1#email.comm",
"group_id": "1",
"created_at": "2017-08-11 02:16:41",
"disable_auto_group_change": "0",
"firstname": "Jane",
"lastname": "Doe",
"created_in": "New Zealand Store View"
}
}
I have been using a tool, JSON-to-Go, to help me create the struct types, however it doesn't look quite right for this style of response:
type AutoGenerated struct {
Num0 struct {
EntityID string `json:"entity_id"`
WebsiteID string `json:"website_id"`
Email string `json:"email"`
GroupID string `json:"group_id"`
CreatedAt string `json:"created_at"`
DisableAutoGroupChange string `json:"disable_auto_group_change"`
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
CreatedIn string `json:"created_in"`
} `json:"0"`
Num1 struct {
EntityID string `json:"entity_id"`
WebsiteID string `json:"website_id"`
Email string `json:"email"`
GroupID string `json:"group_id"`
CreatedAt string `json:"created_at"`
DisableAutoGroupChange string `json:"disable_auto_group_change"`
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
CreatedIn string `json:"created_in"`
} `json:"1"`
}
All I am interested in is the inner JSON - the stuff to actually do with the customer. I am looping over this to extract some information.
How do I create the required struct to read from this?
I have looked at any number of documents or articles but they tend to use more simple JSON responses as examples.
For your JSON structure following might suit well.
Play Link: https://play.golang.org/p/ygXsdYALCb
Create a struct called Info or name you prefer also customize your field names as you like.
type Info struct {
EntityID string `json:"entity_id"`
WebsiteID string `json:"website_id"`
Email string `json:"email"`
GroupID string `json:"group_id"`
CreatedAt string `json:"created_at"`
DisableAutoGroupChange string `json:"disable_auto_group_change"`
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
CreatedIn string `json:"created_in"`
}
And create map of Info struct and the unmarshal it.
var result map[string]Info
if err := json.Unmarshal(jsonBytes, &result); err != nil {
fmt.Println(err)
}
fmt.Printf("%+v", result)
EDIT:
As asked in the comment, adding for example:
fmt.Println("Accessing unmarshal values:")
for key, info := range result {
fmt.Println("Key:", key)
fmt.Printf("Complete Object: %+v\n", info)
fmt.Println("Individual value, typical object field access:")
fmt.Println("EntityID:", info.EntityID)
fmt.Println("Email:", info.Email)
}
Well, first, I don't like the auto-generated struct definitions there. I would change that to look like this
type Customer struct {
EntityID string `json:"entity_id"`
WebsiteID string `json:"website_id"`
Email string `json:"email"`
GroupID string `json:"group_id"`
CreatedAt string `json:"created_at"`
DisableAutoGroupChange string `json:"disable_auto_group_change"`
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
CreatedIn string `json:"created_in"`
}
You may want to create a wrapper type
type Customers map[string]Customer
This should work with your json that you've provided. To put this together
customers := Customers{}
err := json.Unmarshal(jsonBytes, &customers)
Both #Xibz and #jeevatkm provided great solutions. However, in some cases, not all JSON structures can be unmarshalled into Go structures. You may have to define your own decoding functions.
You can also try gorilla's schema package if you have to define your own decoding function for particular data type or structures.
https://github.com/gorilla/schema