Correct structure for json unmarshal - arrays

I can't figure out how to build a structure for this json object in golang:
{
"response": [1702487, {
"uid": 150261846,
"first_name": "Олег",
"last_name": "Брейн"
}, {
"uid": 53260546,
"first_name": "Олег",
"last_name": "Лобацевич"
}
]
}
As you can see there is no keys names for array and for count too.
Would be glad if you can help

In this situation you'll have to punt and use interface{} somewhere, for example:
package main
import (
"fmt"
"encoding/json"
)
type JsObject struct {
Response []interface{}
}
func main() {
bs := []byte(`{"response":[1702487,{"uid":150261846,"first_name":"Олег","last_name":"Брейн"},{"uid":53260546,"first_name":"Олег","last_name":"Лобацевич"}]}`)
var jso JsObject
json.Unmarshal(bs, &jso)
fmt.Printf("%+v\n", jso)
}

Json to go is quite handy for this sort of thing:
https://mholt.github.io/json-to-go/
If you can remove the spurious 1702487 which makes this a heterogenous list, you should be able to parse it easily into a proper structure, otherwise you might be stuck using interface:
https://play.golang.org/p/w7ebLTuOj9
Presumably you want an array of structs like this:
type Person struct {
UID int `json:"uid"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
}
not sure what 1702487 is but if uid of request, it doesn't really belong in the array.

type AutoGenerated struct {
Response []interface{} `json:"response"`
}

Related

Unmarshal JSON Array in Go

I've read a few answers here and none seem to help. I keep getting the same error:
json: cannot unmarshal array into Go value of type A
type A struct {
Arr []string
}
type MA []A
func UnmarshalJSON() (ma MA, err error) {
jsonFile, err := os.Open(aJsonFile)
// error handling
defer jsonFile.Close()
byteValue, _ := ioutil.ReadAll(jsonFile)
err = json.Unmarshal(byteValue, &ma)
if err != nil {
return ma, err
}
return ma, nil
}
The json looks like this:
[
["Name", "Another Name", "Another"],
["A", "B"],
["W", "X", "Y", "Z"],
["Foo", "Bar"]
]
I've tried various different things from top answers when searching and as previously stated, nothing has worked.
I'm still decently new to Go and having to unmarshall stuff (I'm currently unmarshalling to [][]string but I want to use structs). What am I doing wrong?
A struct has fields; fields have names; the name of the field in your struct is Arr. So the json input would need to be [{ "arr": ["list", "of", "names"]}, {"arr": ["more", "names"]}] for instance, given the example you have above.
You can, however, define an UnmarshalJSON on your type named A, like this:
func (p *A) UnmarshalJSON(data []byte) error {
var s []string
err := json.Unmarshal(data, &s)
if err != nil {
return err
}
p.Arr = s
return nil
}
This receiver function named UnmarshalJSON takes a pointer to an A object, plus some sort of valid json input. Its job is to unmarshal that json. In this case we attempt to unmarshal into an ordinary slice-of-string—the variable s—which works as long as the json itself is a valid initializer for slice-of-strings.
If the unmarshal succeeds we then set p.Arr, knowing that the array is meant just for the thing named Arr (which is in fact the only member of the structure type) and return nil (no error).
Note that the last few lines could be written as:
if err == nil {
p.Arr = s
}
return err
which is shorter, but Go conventions generally handle the error case first, rather than letting it flow through. (I actually prefer the shorter code myself, slightly, but use whatever your group likes.)
(Given an UnmarshalJSON receiver on the type, there probably should be a json marshaler on the type, too, but my minimal test-and-example on the Go playground does not have one.)
your json content should like this
[
{
"Arr": [
"a0",
"a1"
]
},
{
"Arr": [
"b0",
"b1"
]
},
{
"Arr": [
"c0",
"c1"
]
}
]

How to validate JSON when using unmarshal into generic interface?

I want to validate byte array data if it contains valid JSON using unmarsall method into interface.
package main
import (
"encoding/json"
"fmt"
)
func isJSON(s string) bool {
var js map[string]interface{}
return json.Unmarshal([]byte(s), &js) == nil
}
func main() {
var tests = []string{
`{"a":"b"}`,
`[{"a":"b"},{"a":"b"}]`,
}
for _, t := range tests {
fmt.Printf("isJSON(%s) = %v\n\n", t, isJSON(t))
}
}
Both input test parameters are valid JSON strings, but it validate based on the interface 'map[string]interface{}'
{
"a": "b"
}
[{
"a": "b"
}, {
"a": "b"
}]
I want to validate the JSON text. JSON text is a serialized object or array. Hence looking for a solution which support all valid cases for JSON text as I added test cases in playground.
How can I make this interface i.e var map[string]interface{} generic so it support both test cases of valid JSON string?
Solved: Playground Link
Don't use map[string]interface{} but simply interface{}. The second example is of type []interface{} and there are more types of valid json.
Here your working code. I added a few more cases of valid json.
playground
Here the code if you want to allow only maps and slices:
playground

Parse embedded Struct form values in GoLang

I have a struct that includes an array of another struct, eg
type Struct1 struct {
Value string
Items []Struct2
}
type Struct2 struct {
Value string
}
I am using gorilla schema to decode my Form values into Struct 1.
The values for the embedded struct, Struct 2, are not coming through.
When I look at the logs for the FormValue("Struct2") it returns '[Object object], [Object object]'
Any help would be greatly appreciated
EDIT
An example of the structure of the form,
Using AngularJS,
var data = $scope.struct1;
$http({
method: 'POST',
url:url,
data : data,
headers : {'Content-Type': 'application/x-www-form-urlencoded'},
transformRequest: function(obj) {
var str = [];
for(var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
}
})
.then(function successCallback(response) {
console.log(response);
}, function errorCallback(response) {
});
It's possible that you don't have the right struct design for your HTML form. You might want to post your input and/or your HTML form design.
gorilla/schema's decode expects the values input to be passed as a variable of type map[string][]string, as you can see both from the example in the documentation and from the test files in the package. Here's a simple complete script that just wraps the example from the documentation and prints the result:
package main
import(
"fmt"
"github.com/gorilla/schema"
)
type Person struct {
Name string
Phone string
}
func main() {
values := map[string][]string{
"Name": {"John"},
"Phone": {"999-999-999"},
}
person := new(Person)
decoder := schema.NewDecoder()
decoder.Decode(person, values)
fmt.Printf("Person: %v\n", person)
}
That outputs Person: &{John 999-999-999}.
That is the correct form for a map literal of type map[string][]string, as you can demonstrate by performing a declaration followed by an assignment and running it without error:
var values map[string][]string
values = map[string][]string{
"Name": {"John"},
"Phone": {"999-999-999"},
}
Now map[string][]string doesn't obviously support all the types that gorilla/schema supports, such as the type in your question: slices of structs. But the HTML form is processed such that a translation makes sense: it keeps appending indices and field names with dot separators to create the desired structure. So for the types you posted in your question, I wrote this script to decode values into the structs:
package main
import(
"fmt"
"github.com/gorilla/schema"
)
type Struct1 struct {
Value string
Items []Struct2
}
type Struct2 struct {
Value string
}
func main() {
values := map[string][]string{
"Value": {"the thing with the items"},
"Items.0.Value": {"a"},
"Items.1.Value": {"b"},
"Items.2.Value": {"c"},
}
s1 := new(Struct1)
decoder := schema.NewDecoder()
decoder.Decode(s1, values)
fmt.Printf("S1: %v\n", s1)
}
Running that outputs:
S1: &{the thing with the items [{a} {b} {c}]}
That demonstrates that decode can populate your struct design without error, if its input matches that design.
So you might try to verify that your input matches that scheme -- that it has those array-like indices and field names with the dot separator in a way that conforms to your struct design. And if it does not, that indicates that your struct design needs to be updated to fit the format of your input.
You can see examples of decode working on this type of structure in the decode_test.go file in the gorilla/schema package, such as these lines:
type Foo struct {
F01 int
F02 Bar
Bif []Baz
}
type Bar struct {
F01 string
F02 string
F03 string
F14 string
S05 string
Str string
}
type Baz struct {
F99 []string
}
func TestSimpleExample(t *testing.T) {
data := map[string][]string{
"F01": {"1"},
"F02.F01": {"S1"},
"F02.F02": {"S2"},
"F02.F03": {"S3"},
"F02.F14": {"S4"},
"F02.S05": {"S5"},
"F02.Str": {"Str"},
"Bif.0.F99": {"A", "B", "C"},
}
The Foo struct has a field named Bif of type []Baz. Baz is a struct -- so we have a slice of structs type, like in your question. Baz has a field named F99. You can see that the input is referenced with the string value "Bif.0.F99".
Use this and other examples in the test file as your guide.

how to parse structs in golang and print the items from the struct?

Here is a similar example: Parsing JSON in GoLang into struct
I am getting a json response from the server and I only need to get certain data.
I've created a sample code:
package main
import (
"fmt"
"encoding/json"
)
type response struct {
Response []struct {
Stats struct {
A int `json:"a"`
B float64 `json:"b"`
C int `json:"c"`
D float64 `json:"d"`
E float64 `json:"e"`
F float64 `json:"f"`
G float64 `json:"g"`
H float64 `json:"h"`
I float64 `json:"i"`
J float64 `json:"j"`
} `json:"stats"`
Data []struct {
Num0 int64 `json:"0"`
Num1 interface{} `json:"1"`
} `json:"data"`
} `json:"response"`
}
func main() {
src := `
{
"response": [{
"stats": {
"a": 458,
"b": 302.3738,
"c": 0,
"d": 706.777,
"e": 2.423,
"f": 238.73375,
"g": 68.971,
"h": 85.1989781659389,
"i": 84.6381777592766,
"j": 292658.49
},
"data": [
[1453222860000, null],
[1453223160000, 3.769],
[1453223220000, 37.464]
]
}
]
}
`
var g response
json.Unmarshal([]byte(src), &g)
fmt.Println(g.Response[0].Stats)
}
The output I get is
`{458 302.3738 0 706.777 2.423 238.73375 68.971 85.1989781659389 84.6381777592766 292658.49}
`
I want to get certain items from just the stat struct. Let's say I want to print the value of A or J from the stats struct. How do I do that?
I don't really need the data struct. The json response I got from the server gave me those data but I dont really need it. Anyway, my question is how do I get only certain items only in the Stats struct?
Any suggestion on how to do this or even improve my structs format?
Thanks!
You can simply omit any piece of the structure you don't care about. The JSON package will silently ignore anything present in the source JSON that isn't present in the destination structure. Thus if you don't care about the Data portion, omit it from the structure. If you only care about A and J in the stats section, only include those.
type response struct {
Response []struct {
Stats struct {
A int `json:"a"`
J float64 `json:"j"`
} `json:"stats"`
} `json:"response"`
}
https://play.golang.org/p/W3bmlf15sF
Edit: Also worth noting that you don't need to include the struct tags if they are just lowercases of the field names, as the JSON package will match fields that only differ by capitalization (though it prefers exact matches, if there's ambiguity).

How can we initialize an array of type struct (which stores the json output) within a struct in golang

I need to initialize the following data structure which will store a json. The Attack_plans will hold multiple plans and if I loop through the GeneratePlan struct, I need all the plans that were stored.
type GeneratePlan struct {
Mode string `json:"mode"`
Name string `json:"name"`
Schema string `json:"schema"`
Version string `json:"version"`
Attack_plans []struct {
Attack_plan *Attack_plan `json:"attack-plan"`
} `json:"attack-plans"`
}
type Attack_plan struct {
Attack_resources []struct {
Attack_resource *Attack_resource `json:"attack-resource"`
} `json:"attack-resources"`
}
Can anyone please suggest something? If the data structure needs to be simplified before initializing it, then please suggest that as well. I am very new to golang so please ignore the best practices to follow. Any help is appreciated. Thanks!
why don't u just json.marshal your object to a json string, you can got answer
generatePlan := GeneratePlan{
Mode: "mode",
Name: "name",
Schema: "sachema",
Version: "version",
Attack_plans: []struct {
Attack_plan *Attack_plan `json:"attack-plan"`
}{
{Attack_plan: &Attack_plan{[]struct {
Attack_resource *Attack_resource `json:"attack-resource"`
}{
{Attack_resource: new(Attack_resource)},
{Attack_resource: new(Attack_resource)},
}}},
{Attack_plan: &Attack_plan{[]struct {
Attack_resource *Attack_resource `json:"attack-resource"`
}{
{Attack_resource: new(Attack_resource)},
{Attack_resource: new(Attack_resource)},
}}},
},
}
I found the solution! This simplifies the above data structure!
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"`
}

Resources