Microsoft calendar event response to Go struct - go

been trying to unmarshal a response from Microsoft's Graph API into a Go struct but I keep getting an error "json: cannot unmarshal object into Go struct field .value.start of type []struct { DateTime string "json:"dateTime""; TimeZone string "json:"timeZone"" }".
Below is my struct:
type MicrosoftCalendarEventsResponse struct {
Value []struct {
Etag string `json:"#odata.etag"`
Id string `json:"id"`
Subject string `json:"subject"`
Start []struct {
DateTime string `json:"dateTime"`
TimeZone string `json:"timeZone"`
} `json:"start"`
End []struct {
DateTime string `json:"dateTime"`
TimeZone string `json:"timeZone"`
} `json:"end"`
OriginalStartTimeZone string `json:"originalStartTimeZone"`
OriginalEndTimeZone string `json:"originalEndTimeZone"`
ICalUId string `json:"iCalUId"`
ReminderMinutesBeforeStart int `json:"reminderMinutesBeforeStart"`
IsReminderOn bool `json:"isReminderOn"`
} `json:"value"`
}
The response I received is this:
{"#odata.etag":"W/\"8COqS12xxxhwcMA==\"","id":"xxxxx","createdDateTime":"2019-12-05T17:09:41.018502Z","lastModifiedDateTime":"2019-12-05T17:09:41.8919929Z","changeKey":"xxxx","categories":[],"originalStartTimeZone":"W. Europe Standard Time","originalEndTimeZone":"W. Europe Standard Time","iCalUId":"xxx","reminderMinutesBeforeStart":15,"isReminderOn":true,"hasAttachments":false,"subject":"Something","bodyPreview":"","importance":"normal","sensitivity":"normal","isAllDay":false,"isCancelled":false,"isOrganizer":true,"responseRequested":true,"seriesMasterId":null,"showAs":"busy","type":"singleInstance","webLink":"xxx","onlineMeetingUrl":null,"isOnlineMeeting":false,"onlineMeetingProvider":"unknown","allowNewTimeProposals":true,"recurrence":null,"onlineMeeting":null,"responseStatus":{"response":"organizer","time":"0001-01-01T00:00:00Z"},"body":{"contentType":"html","content":""},"start":{"dateTime":"2019-12-17T17:00:00.0000000","timeZone":"UTC"},"end":{"dateTime":"2019-12-17T17:30:00.0000000","timeZone":"UTC"},"location":{"displayName":"","locationType":"default","uniqueIdType":"unknown","address":{},"coordinates":{}},"locations":[],"attendees":[],"organizer":{"emailAddress":{"name":"John Doe","address":"someone#somewhere.com"}}}
In which you can clearly see the part that is giving the error:
"start":{"dateTime":"2019-12-17T17:00:00.0000000","timeZone":"UTC"}
can anyone please tell me what I am doing wrong? been trying for hours without any progress and I really have no clue whats wrong.
The other stuff like Etag, Id, Subject and so on are working properly. Its only the nested []structs that do not work.

To capture calender events (plural) it makes sense that the top-level Values is a slice of structs.
However, within a particular Value, your Start and End fields are defined also as slices of structs which is probably not what you want.
Try just a plain struct:
Start struct {
DateTime string `json:"dateTime"`
TimeZone string `json:"timeZone"`
} `json:"start"`
End struct {
DateTime string `json:"dateTime"`
TimeZone string `json:"timeZone"`
} `json:"end"`

Related

How to access the fields of this struct in Golang

I'm new to Golang and I need to know how to access the value from a struct of the format:
type CurrentSkuList struct {
SubscriptionNumber string `json:"subscriptionNumber`
Quantity int `json:"quantity"`
SubscriptionProducts []struct {
ID int `json:"id"`
ActiveStartDate int `json:"activeStartDate"`
ActiveEndDate int `json:"activeEndDate"`
Status string `json:"status"`
Sku string `json:"sku"`
ChildIDs []int `json:"childrenIds"`
} `json:"subscriptionProducts"`
}
For example, if I have a variable currentSkus of type CurrentSkuList and I need to access only Sku and Status values, is there a way to do something like:
currentSkus.SubscriptionProducts.Sku?
EDIT! When I try to access currentSkus.Quantity I get a compiler error undefined (type []util.CurrentSkuList has no field or method Quantity).
Yeah, there is a way. You can access by the . syntax you proposed. In this case, CurrentSkuList is returning an slice of SubscriptionProduct, you know that because of the [] struct part. Then you would have to access to the data this way:
currentSkus.SubscriptionProducts[index].Sku

How can I get this type of data in Go lang?

This is API response data, looks like this.
{
"result":1,
"message":"",
"pds": [
{
"state":"Y",
"code":13,
"name":"AAA",
"price":39900,
},
{
"state":"Y",
"code":12,
"name":"BBB",
"price":38000,
}
],
"request":
{
"op":"new",
}
}
How can I get this data in Go lang?
I tried json.Unmarshall and get with map[string]interface{} but it looks like I used the wrong type to get the data.
Should I use structure??
You need to create a struct to handle this properly if you don't want the json.Unmarshall output to be a map[string]interface{}.
If you map this JSON object to a Go struct you find the following structure:
type APIResponse struct {
Result int `json:"result"`
Message string `json:"message"`
Pds []struct {
State string `json:"state"`
Code int `json:"code"`
Name string `json:"name"`
Price float64 `json:"price"`
} `json:"pds"`
Request struct {
Op string `json:"op"`
} `json:"request"`
}
You also can find a great tool to convert JSON objects to Go structs here
If you don't want to use the native json.Unmarshall, here's a good option to use the package go-simplejson.
Documentation

Go struct separation best practices

I am trying to figure out a decent approach toward dealing with multiple uses for a struct. Let me explain the scenario.
I have a struct that represents the Model in gorm. In the current implementation, I have validation bound to this struct so when a request hits the endpoint I would validate against the model's struct. This works fine for most cases. But then there are some instances where I want to have more control over the request and the response.
This is possible by introducing a few additional internal structs that will parse the request and response. And I can decouple the validation from the model into the request specific struct. I am trying to figure out what the best practice is around these patterns. Pretty sure a lot of peeps would have faced a similar situation.
// Transaction holds the transaction details.
type Transaction struct {
Program Program
ProgramID uuid.UUID
Type string
Value float64
Reference string
}
// TransactionRequest for the endpoint.
type TransactionRequest struct {
ProgramKey string `json:"program_key" validator:"required"`
Type string `json:"type" validator:"required,oneof=credit debit"`
Value float64 `json:"value" validator:"required,numeric"`
Reference string `json:"reference" validator:"required"`
}
Update:
I managed to find a balance by introducing additional tags for update requests, I wrote about how I achieved it here
I faced similar problem and for solving that, defined a method for validating and didn't use tags. I had to, because I follow DDD and we should validate in service layer not API layer.
here is a sample of my apporach:
type Station struct {
types.GormCol
CompanyID types.RowID `gorm:"not null;unique" json:"company_id,omitempty"`
CompanyName string `gorm:"not null;unique" json:"company_name,omitempty"`
NodeCode uint64 `json:"node_code,omitempty"`
NodeName string `json:"node_name,omitempty"`
Key string `gorm:"type:text" json:"key,omitempty"`
MachineID string `json:"machine_id,omitempty"`
Detail string `json:"detail,omitempty"`
Error error `sql:"-" json:"user_error,omitempty"`
Extra map[string]interface{} `sql:"-" json:"extra_station,omitempty"`
}
// Validate check the type of
func (p *Station) Validate(act action.Action) error {
fieldError := core.NewFieldError(term.Error_in_companys_form)
switch act {
case action.Save:
if p.CompanyName == "" {
fieldError.Add(term.V_is_required, "Company Name", "company_name")
}
if p.CompanyID == 0 {
fieldError.Add(term.V_is_required, "Company ID", "company_id")
}
}
if fieldError.HasError() {
return fieldError
}
return nil
}
file's address: https://github.com/syronz/sigma-mono/blob/master/model/station.model.go

Golang Decode a BSON with special character Keys to a struct

I have a Golang struct called Person where all the properties have to be exported:
type Person struct {
Id string
Name string
}
Now I need to encode my MongoDB BSON response to this Person struct. The BSON looks like:
{
"_id": "ajshJSH78N",
"Name": "Athavan Kanapuli"
}
The Golang code to encode the BSON is:
mongoRecord := Person{}
c := response.session.DB("mydb").C("users")
err := c.Find(bson.M{"username": Credentials.Username, "password": Credentials.Password}).One(&mongoRecord)
The Problem:
_id is not getting encoded into Id
If I change the Person property into _Id, then it won't be exported.
How can I solve this problem?
Define your struct with json tag-
type Person struct {
Id string `json:"_id"`
Name string // this field match with json, so mapping not need
}
I tried to put a json tag like ,
type Person struct {
Id string `json:"_id"`
Name string // this field match with json, so mapping not need
}
But still it didn't work. Because the Mongodb returns '_id' which is of type bson.ObjectId . Hence changing the Struct tag to bson:"_id" and the type of the Person struct has been changed from string to bson.ObjectId. The changes done are as follows ,
type Person struct {
Id bson.ObjectId `bson:"_id"`
Name string
UserName string
IsAdmin bool
IsApprover bool
}
And It works!

How can I add a new boolean property to a Golang struct and set the default value to true?

I have a user struct that corresponds to an entity. How can I add a new property active and set the default value to true?
Can I also set the value of that property to true for all existing entities by some easy method?
type User struct {
Id int64 `json:"id"`
Name string `json:"name"`
}
Bonus questions: I don't quite understand the syntax in the struct. What do the three columns represent? What do the JSON strings have ``around them?
//You can't change declared type.
type User struct {
Id int64 `json:"id"`
Name string `json:"name"`
}
//Instead you construct a new one embedding existent
type ActiveUser struct {
User
Active bool
}
//you instantiate type literally
user := User{1, "John"}
//and you can provide constructor for your type
func MakeUserActive(u User) ActiveUser {
auser := ActiveUser{u, true}
return auser
}
activeuser := MakeUserActive(user)
You can see it works https://play.golang.org/p/UU7RAn5RVK
You have to set the default value as true at the moment when you are passing the struct type to a variable, but this means you need to extend that struct with a new Active field.
type User struct {
Id int64 `json:"id"`
Name string `json:"name"`
Active bool
}
user := User{1, "John", true}
json:"id" means that you are mapping the json decoded object field to the field id in your struct type. Practically you are deserialize the json string into object fields which later you can map to their specific field inside the struct.

Resources