How do I Change the Position of Golang Struct Values? - arrays

How would I change the position of the json values?
What Im trying to achieve:
[{"key":"f","value":"f"},{"value":"f","key":"f"}]
Problem:
type Struct struct {
Key string `json:"key"`
Value string `json:"value"`
}
func main() {
test := []Struct{ {Key: "test",Value: "wep"}, {Value: "wep",Key: "test"}}
bytes, _ := json.Marshal(test)
fmt.Print(string(bytes))
}
Running this code prints [{"key":"test","value":"wep"},{"key":"test","value":"wep"}]
I have also tried doing something like this but it just printed empty values
type Struct struct {
Key string `json:"key"`
Value string `json:"value"`
Value2 string `json:"value"`
Key2 string `json:"key"`
}
But how would I be able to switch the position of the key and value field around?

type StructA struct {
Key string `json:"key"`
Value string `json:"value"`
}
type StructB struct {
Value string `json:"value"`
Key string `json:"key"`
}
func main() {
test := []interface{}{
StructA{Key: "test", Value: "wep"},
StructB{Value: "wep", Key: "test"},
}
bytes, _ := json.Marshal(test)
fmt.Print(string(bytes))
}
https://play.golang.org/p/72TWDU1BMaL

If you're using json.Marshal provided by official package it's not passible to do that. In stead, you can implement your own MarhalJSON method so that you can decide the position of your struct fields.

To the question "can I make a single struct type serialize its fields in a different order or different occasions ?" :
there isn't a simple way to do this.
Regarding struct fields : the code you write shows the assigning operations in a given order, but once your code is compiled, there is no trace of that order anymore.
If you really need this (side note : I would be curious to know about your use case ?), you could create a custom type, with its own .MarshalJSON() method, which would hold a value indicating "fields should be serialized in this order".
If what you need is to send an array of heterogeneous objects, use separate struct types, and an []interface{} array :
type Obj1 struct{
Key string `json:"name"`
Value string `json:"value"`
}
type Obj2 struct{
Value string `json:"value"`
Key string `json:"name"`
}
func main() {
test := []interface{}{ Obj1{Key: "test",Value: "wep"}, Obj2{Value: "wep",Key: "test"}}
bytes, _ := json.Marshal(test)
fmt.Print(string(bytes))
}
https://play.golang.org/p/TOk28gL0eSK

Related

Golang for loop with multiple brackets

I've stumbled upon this repository,
https://github.com/prometheus-community/jiralert/blob/a0f0e80e575e71cbf7db565d3296a3a984282dff/pkg/config/config_test.go#L148
The for loop has multiple brackets:
for _, test := range []struct {
missingField string
errorMessage string
}{
{"Name", "missing name for receiver"},
(...)
} {
fields := removeFromStrSlice(mandatory, test.missingField)
(...)
}
configErrorTestRunner(t, config, test.errorMessage)
}
I haven't been able to find anything about this in the go documentation, what is this construct?
The first bracket pair is part of the struct type definition which has the syntax:
struct{
field1 type1
field2 type2
...
}
The second pair is part of the composite literal value, creating a value for the slice of this struct. It has the syntax of:
[]elementType{value1, value2, ...}
The inner, embedded brackets are part of the composite literals creating the struct values of the slice. The type is omitted (it's known from the slice type), so each {field1Value, fieldValue2...} is a struct value.
The third pair defines the block of the for statement. The for statement iterates over the elements of the slice defined by the mentioned composite literal.
To clean up the code for better readability and understanding. Whatever you gave was equivalent to:
type TestStruct struct {
missingField string
errorMessage string
}
testCase := TestStruct {
{
missingField: "Name",
errorMessage: "missing name for receiver",
}
(...)
}
for _, test := range(testCase) {
fields := removeFromStrSlice(mandatory, test.missingField)
}
configErrorTestRunner(t, config, test.errorMessage) is probably from a parent test func

Difference between initialization of struct slices

type Person struct {
ID int `json:"id"`
}
type PersonInfo []Person
type PersonInfo2 []struct {
ID int `json:"id"`
}
Is there have difference between PersonInfo (named slice of named structs) and PersonInfo2 (named slice of unnamed structs)
The main difference is how you have to initialize Person objects outside of the PersonInfo/PersonInfo2 initialization. Since PersonInfo2 is an array of the anonymous struct type we know nothing about this type outside of the PersonInfo2 initialization.
So they can both be initialized like this:
m := PersonInfo{{1}, {2}}
n := PersonInfo2{{1},{2}}
However if we want to append an element of the anonymous struct type we would have to specify the full type:
append(n, struct { ID int `json:"id"` }{3})
If we print these out we can see they appear to be the same:
fmt.Printf("%+v\n%+v", m, n)
Outputs:
[{ID:1} {ID:2}]
[{ID:1} {ID:2}]
However they wont be deeply equal because PersonInfo is an array of type Person and PersonInfo2 is an array of anonymous struct type. So the following:
if !reflect.DeepEqual(m,n) {
print("Not Equal")
}
will print "Not Equal".
Here is a link to see for yourself.
When appending to PersonInfo2 we have to repeat the anonymous struct type for every value we want to append, it is probably better to use PersonInfo as an array of type Person.
Go is using structural typing, that means, as long as the two types have the same underlying type, they are equivalent.
So, for your question: Person and struct{ ID int 'json:"id"'} is equivalent because they have the same underlying type, and therefore, PersonInfo and PersonInfo2 are also equivalent. I took of the json tags to simplify the example.
person1 := Person{1}
pStruct1 := struct{ID int}{2}
pInfo1 := PersonInfo{
person1,
pStruct1,
}
pInfo2 := PersonInfo2{
person1,
pStruct1,
}
fmt.Printf("%+v\n", pInfo1)
fmt.Printf("%+v", pInfo2);
//outputs
//PersonInfo: [{ID:1} {ID:2}]
//PersonInfo2: [{ID:1} {ID:2}]
Code example: https://play.golang.org/p/_wlm_Yfdy2
type PersonInfo is an object of Person, while PersonInfo2 is a class (or type in Golang) by itself. Even though their data structure is similar.
So, when you run DeepEqual() to check the similarity it will turn out to be false.
Example by previous comment:
if !reflect.DeepEqual(m,n) {
print("Not Equal")
}
Hope this helps.

How to query from datastore if the value is in the array struct in go

I have two structs
type Parent struct {
Text string
Childs []ChildValue
}
type ChildValue struct {
Name string
Value int32 `json:"value" datastore:"value" validate:"required,min=1,max=5"`
}
The value in childValue can be from 1 to 5.
I want to be able to filter if value in array is more than 2
query = query.Filter("childs.value =>", "2")
It there a simple way to do that?

Struct with interface type fields

Why is it I can't have this in golang?
type EventDefinition struct {
Name string
EventProperties interface{}
}
Where EventProperties can be one of may types of structs, each struct with different fields. The idea is to have an EventDefinition with EventProperties
type Party struct {
Location string
Hour string
}
or
type Wedding struct {
Bride string
Groom string
Hour string
}
or
type Graduation struct {
Location string
Graduate string
}
Found my problem. The problem was not related to this issue, the problem was
Location : event.Party.Location.(string),
At some point in my implementation I was doing this when Location was a nil interface{}, hence the blowup.
As a response to this, it is possible to do what I mentioned.

Nilable value in appengine/datastore using Go

The list of supported types by datastore doesn't contain pointer types (https://cloud.google.com/appengine/docs/go/datastore/reference).
How then can I represent a value that can and sometimes should be nil?
For example in the following structure I need the DailyValuePercent to be nilable to explicitly say that the value is missing.
type NutritionFact struct {
Name string `datastore:",noindex" json:"name"`
DailyValuePercent int `datastore:",noindex" json:"dailyValuePercent"`
}
Since I can't use *int as the field type for datastore then how to represent an optional value?
Either store your ints as strings (with empty string => no value) or use a composite type like:
type NillableInt struct {
i int
isNil bool // or isNotNil bool if you want different default semantics
}
Adapt to your performance vs. memory usage requirements.
If you want your code to deal with int pointers but persist nil values in the datastore, define your struct like this:
type NutritionFact struct {
Name string `datastore:",noindex" json:"name"`
DailyValuePercent int `datastore:"-"`
}
And implement the PropertyLoadSaver interface where you will save/load an int value and a isNil boolean.

Resources