how to initialize the struct of following structure in golang - json

I have the following data structure. I need to initialize it without using nested initialization. This data structure will be flushed to output a json file later.
type GeneratePlan struct{
Mode string `json:"mode"`
Name string `json:"name"`
Schema string `json:"schema"`
Version string `json:"version"`
Attack_plans []struct1 `json:"attack-plans"`
}
type struct1 struct {
Attack_plan Attack_plan `json:"attack-plan"`
}
type Attack_plan struct{
Attack_resouces []struct2 `json:"attack-resources"`
}
type struct2 struct {
Attack_resource Attack_resource `json:"attack-resource"`
}
Problem is when I try to append the variable of type struct2 to the Attack_resources[] slice, it gives the error as
cannot use struct2 (type *structs.Struct2) as type structs.Struct2 in append
How can we initialize the struct without using new or any ptr? As, if we use any of the standard struct initialization technique, it will give the above error.
If I change the above data structure and make it hold a pointer to another struct, it doesn't store the values correctly. I am very new to golang. Any help is appreciated. Thanks in advance!

You can initialize a struct value using:
resource := struct2{}
As #nothingmuch pointed out, if you have a struct pointer and need the underlying value, you can dereference the pointer using:
deref := *resource

Related

Accessing Data in Nested []struct

I'm working on unmarshaling some nested json data that I have already written a struct for. I've used a tool that will generate a struct based off json data, but am a bit confused how to work with accessing nested json data (and fields can sometimes be emtpy).
Here is an example of struct:
type SomeJson struct {
status string `json:"status"`
message string `json:"message"`
someMoreData []struct {
constant bool `json:"constant,omitempty"`
inputs []struct {
name string `json:"name"`
type string `json:"type"`
} `json:"inputs,omitempty"`
Name string `json:"name,omitempty"`
Outputs []struct {
Name string `json:"name"`
Type string `json:"type"`
} `json:"outputs,omitempty"`
I'm able to unmarshal the json data and access the top level fields (such as status and message), but am having trouble accessing any data under the someMoreData field. I understand this field is a (I assume an unknown) map of structs, but only have experience working with basic single level json blobs.
For reference this is the code I have to unmarshal the json and am able to access the top level fields.
someData := someJson{}
json.Unmarshal(body, &someData)
So what is exactly the best to access some nested fields such as inputs.name or outputs.name?
to iterate over your particular struct you can use:
for _, md := range someData.someMoreData {
println(md.Name)
for _, out := range md.Outputs {
println(out.Name, out.Type)
}
}
to access specific field:
someData.someMoreData[0].Outputs[0].Name
Couple of things to note:
The struct definition is syntactically incorrect. There are couple of closing braces missing.
type is a keyword.
The status and message and other fields with lower case first letter fields are unexported. So, the Json parser will not throw error, but you will get zero values as output. Not sure that's what you observed.
someMoreData is an array of structs not map.

mgo error when unmarshal map[string]interface{}

I want to store an arbitrary json object in a struct:
type C struct {
Name string `json:"name" bson:"name"`
Config map[string]interface{} `json:"config" bson:"config"`
}
This works fine when I store any deeply nested json object, but when I go retrieve it and mgo tries to Unmarshal it, I get:
Unmarshal can't deal with struct values. Use a pointer.
I'm not sure what's supposed to be a pointer. I get the same errors if I change it to:
Config *map[string]interface{}
The error occurs here: https://github.com/MG-RAST/golib/blob/master/mgo/bson/bson.go#L493
I don't know what it's reflecting on though.
So when you are unmarshaling the input argument takes a pointer to the struct, and you need to define a type in order to use a pointer to a struct.
type myMap map[string]interface{}
Then you can make a pointer to that type notice the ampersand to indicate pointer to your struct for type myMap, with json you could do something like so:
json := []Byte{`{"name": "value"}`}
c := &myMap{"value": "name"}
json.Unmarshal(c, json)
So you need *myMap to the struct not a pointer to the type. In order to explain the specific solution to this problem you need to add the context of how mongodb is unmarshaling your json.

Unmarshal dynamic json content in Go

I have a dynamic json object which I want to unmarshal in my Go app. The problem is that some parts of the json are dynamically named, so I don't know what to put in the struc type json tags. To illustrate my problem, please see this playground: https://play.golang.org/p/q8J0VVO7uj
As you can see the s1 can perfectly be unmarshalled, because the struct type indeed has tag description. But s2 cannot be unmarshalled.
So my question is: how can I solve this? Can I make use of interfaces here?
Use a map for dynamic keys:
type ElvisEvent struct {
Timestamp int64 `json:"timestamp"`
Type string `json:"type"`
AssetID string `json:"assetId"`
Metadata struct {
} `json:"metadata"`
ChangedMetadata map[string]struct {
OldValue interface{} `json:"oldValue"`
NewValue interface{} `json:"newValue"`
} `json:"changedMetadata"`
}
playground example

Handling two forms of JSON?

I'm writing an application in Go that will recieve two forms of JSON:
Example 1:
{"book_data":{"title":"book-title","page_number":457}}
Example 2:
{"book_data":{"collection":214},"books":{"data":[{"title":"book-title","page_number":457},{"title":"book-title","page_number":354}]}}
I thought that I could create a struct like the following and unmarshal JSON into it:
type Book struct {
Title string `json:"title"`
PageNumber int `json:"page_number"`
}
but that only works for the first example.
How can I handle JSON from both examples?
You can first unmarshal partly in json.RawMessage to next decide depending of unmarshalled payload. And you also can just unmarshal in more generic structure. Something like
type Book struct {
Title string `json:"title"`
PageNumber int `json:"page_number"`
}
type BookShelf struct {
BookData struct {
Book
Collection int `json:"collection"`
} `json:"book_data"`
Books struct {
Data []Book `json:"data"`
} `json:"books"`
}
which for me looks readable, meaningful and handy enough for further processing.
Why not unmarshal to a map[string]interface{} and then use the result to see which form you need to handle? You can then deserialize with a specific struct type for each form.
Another way would be to use the following package to check for differing attributes, so you can decide which struct to use for the real unmarshaling.
https://github.com/go-xmlpath/xmlpath/tree/v2
You can unmarshal to map because your key is string and value may be anything like - map[string]interface{}. If you are not sure any data type or value then use interface{} beacause it can store any value. Then use result to see which form it is, And deserialize to specific struct type.
Another way to convert JSON to go struct is use this tool.
https://mholt.github.io/json-to-go/

Json unmarshalling in GO

I am trying to unmarshal a json response from the server into various types, but I
am not finding how to do it.
The types which work are :-
type ServerResponse struct {
Total int
Data []User
}
type User struct {
Name string
Age int
}
and I can successfully unmarshal the json and receive the expected User type.
What I want to do is handle various server responses and convert after the
fact. eg.
type ServerResponse struct {
Total int
Data []ServerItem
}
type User struct {
ServerItem
Name string
Age int
}
type Book struct {
ServerItem
Name string
Author string
}
Then use either User(response.Data) or response.Data.(User) to make it a
concrete type so that later functions type check correctly.
Please could anyone let me know where to start looking to solve this issue.
I don't think that this can be done easily. Just decode to map[string]interface{} and create your stuff from this.
Here I wrote a simple program that parses json http://play.golang.org/p/51eiswgznR.
You may also want to read the encoding/json docs http://golang.org/pkg/encoding/json/