Remove elements with empty value when no values - go

I want to remove elements with empty value in struct. My script is below. Output of this script is {"keyA":{}}. I used omitempty to KeyA and KeyB. But an element with empty value is left. On the other hand KeyB is not shown. I want to show KeyA when it has values. I don't want to show KeyA when it has no values. Is there way to do this?
Script
package main
import (
"encoding/json"
"fmt"
)
type sample struct {
KeyA struct {
Key1 string `json:"keyA1,omitempty"`
Key2 string `json:"keyA2,omitempty"`
} `json:"keyA,omitempty"`
KeyB string `json:"keyB,omitempty"`
}
func main() {
var s sample
response, _ := json.Marshal(s)
fmt.Println(string(response)) // {"keyA":{}}
}
Thank you so much for your time. And I'm sorry for my immature question.

Try this:
package main
import (
"encoding/json"
"fmt"
)
type KeyA struct {
Key1 string `json:"keyA1,omitempty"`
Key2 string `json:"keyA2,omitempty"`
}
type sample struct {
KeyA *KeyA `json:"keyA,omitempty"`
KeyB string `json:"keyB,omitempty"`
}
func main() {
var s sample
response, _ := json.Marshal(s)
fmt.Println(string(response)) // {}
}
output:
{}

Related

Printf function show struct differently

I am using compile function of regex package which returns pointer of Regexp struct and passing struct in printf function shows me only string not whole struct.
package main
import (
"fmt"
"regexp"
)
func main() {
reg, _ := regexp.Compile(`[0-9a-f]+`)
fmt.Printf("%+v \n", reg)
}
// Output
[0-9a-f]+
But when I created my own struct and initialising with some value and print it then it shows full struct. I am not understanding the concept here.
package main
import (
"fmt"
)
type Exp struct {
a string
b int
}
func main() {
x := &Exp{"akash", 12}
fmt.Printf("%+v \n", x)
}
// Output: &{akash 12}
The regexp.Regexp type implements the fmt.Stringer interface, which is the default verb used in the fmt.Print* methods.
This means that it calls reg.String() when formatting in your first example.
In your second example, your custom type Exp, has no such method, so it uses default Go-formatting of the struct.

Unmarshal YAML returns incomplete result

Input Yaml:
params:
- aws.region: ["us-west-1","us-west-2"]
- aws.s3path: ["s3-path-1", "s3-path-2"]
Code:
package main
import (
"fmt"
"io/ioutil"
"os"
"gopkg.in/yaml.v2"
)
func main() {
var f File
wfyaml, _ := os.Open("temp.yaml")
byteValue, _ := ioutil.ReadAll(wfyaml)
yaml.Unmarshal(byteValue, &f)
fmt.Print(f)
}
type File struct {
Params Params `yaml:"params"`
}
type Params []struct { // <<< This [] behavior is confusing
AwsRegion []string `yaml:"aws.region"`
S3path []string `yaml:"aws.s3path"`
}
Output:
{[{[us-west-1 us-west-2] []} {[] [s3-path-1 s3-path-2]}]}%
If I use
type Params struct { // <<< This [] behavior is confusing
AwsRegion []string `yaml:"aws.region"`
S3path []string `yaml:"aws.s3path"`
}
Then output is {{[] []}}%
I am not sure if I am missing something here.
This is because params from your input yaml is an array.
If you change your input yaml to the following, then you will find your code with type Params struct works as you would expect, because params is no longer an array in this case.
params:
aws.region: ["us-west-1","us-west-2"]
aws.s3path: ["s3-path-1", "s3-path-2"]
The behavior is consistent with the YAML input:
params:
- aws.region: ["us-west-1","us-west-2"]
- aws.s3path: ["s3-path-1", "s3-path-2"]
Above, params is an array, because its elements start with a -. Each - is an array element, and since each element has a key, param is an array of objects. The first element is an object with key aws.region, and the second element is an object with key aws.s3path. These objects are themselves string arrays.

How to set optional parameter after unmarshalling Protobuf ( proto2 ) in Golang?

I have 5 fields in protobuf ( 3 required fileds and 2 optional fileds ). From producer end i will send 3 required fileds (marshall) and get those (unmarshall) 3 required fileds at consumer end. Now, i want to add those two optional parameters values at consumer end . Is it possible ? if yes, how?
Thanks in Advance
To update a field for a struct that is already in memory declare the variable name with the field like the example below.
If someStruct is in memory the value can be overwritten at anytime.
someStruct.SomeField = SomeValue
package main
import (
"fmt"
)
type Data struct {
FieldOne string
FieldTwo int
FieldThree []string
FieldFour float64
}
func main() {
data := createData("A string", 9)
data = data.rcv()
fmt.Println(data)
}
func createData(f1 string, f2 int) *Data {
d := &Data{}
d.FieldOne = f1
d.FieldTwo = f2
return d
}
func (d *Data) rcv() *Data {
d.FieldThree = []string{"string1", "string2"}
d.FieldFour = 1.2
return d
}

How can I parse []int JSON data in Go?

I try parse JSON data include integer array. But, I can't get integer array.
package main
import (
"encoding/json"
"fmt"
)
type Anything struct {
A []int `json:"a"`
}
func main() {
s := "{a:[1,2,3]}"
var a Anything
json.Unmarshal([]byte(s), &a)
fmt.Println(a.A)
}
I got empty array.
[]
How can I get [1, 2, 3]?
{a:[1,2,3]} is not valid JSON. Object keys must be double-quoted. Changing it like this works as expected:
s := "{\"a\":[1,2,3]}"
https://play.golang.org/p/qExZAeiRJy
You have an invalid JSON. You should replace it, for example like this: s := [{"a":[1,2,3]}] or maybe like this s := "[{\"a\":[1,2,3]}]".
You can edit your code to something like this:
package main
import (
"encoding/json"
"fmt"
)
type Anything struct {
A []int `json:"a"`
}
func main() {
// note here: `[{"a":[1,2,3]}]`
// or: s := "[{\"a\":[1,2,3]}]"
s := `[{"a":[1,2,3]}]`
var a []Anything
json.Unmarshal([]byte(s), &a)
fmt.Println(a)
}
Output:
[{[1 2 3]}]
You can run it on https://play.golang.org/p/H4GupGFpfP

Convert data to base64 encode in go

I am new to go programming language and I'm stock on this scenario on my code.
Here's my example code:
a := genreAPI{Genre{"Pop"}, Genre{"Rock"}}
fmt.Println("Value of a :", a)
The current output is: Value of a : [{Pop} {Rock}]
How can I achieved an output like this:
Value of a : [{UG9w} {Um9jaw==}]
which is a base64 encode?
I am not sure what exactly is not clear from the documentation. Not only it has a clear name which explains states what the method is doing, it also has an example.
package main
import (
"encoding/base64"
"fmt"
)
func main() {
data := []byte("Pop")
str := base64.StdEncoding.EncodeToString(data)
fmt.Println(str) // UG9w
}
Go Playground
You can customise the output of print functions by providing a String() method for your type. Either for the whole Genre or just for the name variable.
Example:
package main
import (
"encoding/base64"
"fmt"
)
type Base64String string
func (b Base64String) String() string {
return base64.StdEncoding.EncodeToString([]byte(b))
}
type Genre struct {
Name Base64String
}
func main() {
a := []Genre{Genre{"Pop"}, Genre{"Rock"}}
fmt.Println(a) // prints [{UG9w} {Um9jaw==}]
fmt.Println(string(a[0].Name)) // prints Pop
}

Resources