How to access the fields of this struct in Golang - go

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

Related

Go return struct as JSON in HTTP request

I've defined the following struct in Go:
type repoStars struct {
name string
owner string
stars int
}
And I've created an array repoItems := []repoStars{} which has multiple items of the struct above.
This is how repoItems looks like:
I'm trying to return those items as a JSON response:
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(repoItems)
And it seems empty
What am I doing wrong here?
If the struct fields start with a lower case letter it means unexported. All unexported fields won't be serialised by the encoder.
Change it to capital first letter.
type repoStars struct {
Name string
Owner string
Stars int
}

Dynamically Create Structs in Golang

So I am working with an external API, whose responses I wanted to parse. The incoming responses are of a fixed format i.e.
type APIResponse struct {
Items []interface{} `json:"items"`
QuotaMax int `json:"quota_max"`
QuotaRemaining int `json:"quota_remaining"`
}
So for each response I am parsing the items. Now the items can be of diff types as per the request. It can be a slice of sites, articles, etc. Which have their individual models. like:
type ArticleInfo struct {
ArticleId uint64 `json:"article_id"`
ArticleType string `json:"article_type"`
Link string `json:"link"`
Title string `json:"title"`
}
type SiteInfo struct {
Name string `json:"name"`
Slug string `json:"slug"`
SiteURL string `json:"site_url"`
}
Is there any way, when parsing the input define the type of Items in APIResponse. I don't want to create separate types for individual responses.
Basically want to Unmarshall any incoming response into the APIResponse struct.
Change type of the Items field to interface{}:
type APIResponse struct {
Items interface{} `json:"items"`
...
}
Set the response Items field to pointer of the desired type. Unmarshal to the response:
var articles []ArticleInfo
response := APIResponse{Items: &articles}
err := json.Unmarshal(data, &response)
Access the articles using variable articles.
Run an example on the playground.

Better way of decoding json values

Assume a JSON object with the general format
"accounts": [
{
"id": "<ACCOUNT>",
"tags": []
}
]
}
I can create a struct with corresponding json tags to decode it like so
type AccountProperties struct {
ID AccountID `json:"id"`
MT4AccountID int `json:"mt4AccountID,omitempty"`
Tags []string `json:"tags"`
}
type Accounts struct {
Accounts []AccountProperties `json:"accounts"`
}
But the last struct with just one element seems incorrect to me. Is there a way I could simply say type Accounts []AccountProperties `json:"accounts"` instead of creating an entire new struct just to decode this object?
You need somewhere to store the json string accounts. Using a:
var m map[string][]AccountProperties
suffices, though of course you then need to know to use the string literal accounts to access the (single) map entry thus created:
type AccountProperties struct {
ID string `json:"id"`
MT4AccountID int `json:"mt4AccountID,omitempty"`
Tags []string `json:"tags"`
}
func main() {
var m map[string][]AccountProperties
err := json.Unmarshal([]byte(data), &m)
fmt.Println(err, m["accounts"])
}
See complete Go Playground example (I had to change the type of ID to string and fix the missing { in the json).
As Dave C points out in comments, this is no shorter than just using an anonymous struct type:
var a struct{ Accounts []AccountProperties }
in terms of the Unmarshall call (and when done this way it's more convenient to use). Should you want to use an anonymous struct like this in a json.Marshall call, you'll need to tag its single element to get a lowercase encoding: without a tag it will be called "Accounts" rather than "accounts".
(I don't claim the map method to be better, just an alternative.)

structs with multiple mapping notations

I have these two structs which represent the same entities (one comes from a Json file and the other from a DB)
type DriverJson struct {
ID int `json:"id"`
Name string `json:"name"`
}
type DriverOrm struct {
ID int `orm:"column(id);auto"`
Name string `orm:"column(name);size(255);null"`
}
I want to merge them into one Driver struct, how do I merge the mapping notations (orm:, json:)?
Thank you
As mentioned in the documentation of reflect.StructTag, by convention the value of a tag string is a space-separated key:"value" pairs, so simply:
type DriverJson struct {
ID int `json:"id" orm:"column(id);auto"`
Name string `json:"name" orm:"column(name);size(255);null`
}
For details, see What are the use(s) for tags in Go?

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