Parse JSON in Go - json

This is an example of JSON output when calling 'ListObjects' for AWS S3
{
"Contents": [{
"ETag": "9e2bc2894b23742b7bb688c646c6fee9",
"Key": "DSC-0237.jpg",
"LastModified": "2017-09-06 21:53:15 +0000 UTC",
"Owner": {
"DisplayName": "demo-user",
"ID": "a9e2f170a6880f1d61852df8e523e88ca2a2b7abd093476cc93f1239ab5063c6"
},
"Size": 117904,
"StorageClass": "STANDARD"
}, {
"ETag": "\"9e2bc2894b23742b7bb688c646c6fee9\"",
"Key": "DSC-0238.jpg",
"LastModified": "2017-09-06 21:52:24 +0000 UTC",
"Owner": {
"DisplayName": "demo-user",
"ID": "a9e2f170a6880f1d61852df8e523e88ca2a2b7abd093476cc93f1239ab5063c6"
},
"Size": 117904,
"StorageClass": "STANDARD"
}, {
"ETag": "\"9e2bc2894b23742b7bb688c646c6fee9\"",
"Key": "DSC-0239.jpg",
"LastModified": "2017-09-06 21:53:01 +0000 UTC",
"Owner": {
"DisplayName": "demo-user",
"ID": "a9e2f170a6880f1d61852df8e523e88ca2a2b7abd093476cc93f1239ab5063c6"
},
"Size": 117904,
"StorageClass": "STANDARD"
}],
"IsTruncated": false,
"Marker": "",
"MaxKeys": 5,
"Name": "test-bucket-x011pp3",
"Prefix": ""
}
How do I parse this in Go? Chiefly I am interested in collecting:
Bucket Name
Key
Size
Owner's DisplayName
LastModified
I am coming from Python and in Python it would be something really simple like:
json_result = json.loads(json_string)
bucket_name = json_result['Name']
for idx, obj in enumerate(json_result['Contents']):
key = obj['Key']
size = obj['Size']
lastmod = obj['LastModified']
owner= obj['Owner']['DisplayName']
Thank you for the help!

It is something like this
package main
import (
"bytes"
"encoding/json"
"fmt"
"log"
)
var jsonData = []byte(`
{
"Contents": [{
"ETag": "9e2bc2894b23742b7bb688c646c6fee9",
"Key": "DSC-0237.jpg",
"LastModified": "2017-09-06 21:53:15 +0000 UTC",
"Owner": {
"DisplayName": "demo-user",
"ID": "a9e2f170a6880f1d61852df8e523e88ca2a2b7abd093476cc93f1239ab5063c6"
},
"Size": 117904,
"StorageClass": "STANDARD"
}, {
"ETag": "\"9e2bc2894b23742b7bb688c646c6fee9\"",
"Key": "DSC-0238.jpg",
"LastModified": "2017-09-06 21:52:24 +0000 UTC",
"Owner": {
"DisplayName": "demo-user",
"ID": "a9e2f170a6880f1d61852df8e523e88ca2a2b7abd093476cc93f1239ab5063c6"
},
"Size": 117904,
"StorageClass": "STANDARD"
}, {
"ETag": "\"9e2bc2894b23742b7bb688c646c6fee9\"",
"Key": "DSC-0239.jpg",
"LastModified": "2017-09-06 21:53:01 +0000 UTC",
"Owner": {
"DisplayName": "demo-user",
"ID": "a9e2f170a6880f1d61852df8e523e88ca2a2b7abd093476cc93f1239ab5063c6"
},
"Size": 117904,
"StorageClass": "STANDARD"
}],
"IsTruncated": false,
"Marker": "",
"MaxKeys": 5,
"Name": "test-bucket-x011pp3",
"Prefix": ""
}`,
)
type Response struct {
Contents []*Content
IsTruncated bool
Marker string
MaxKeys int
Name string
Prefix string
}
type Content struct {
ETag string
Key string
LastModified string
Owner *Owner
Size int
StroageClass string
}
type Owner struct {
DisplayName string
ID string
}
func main() {
resp := &Response{}
if err := json.NewDecoder(bytes.NewBuffer(jsonData)).Decode(resp); err != nil {
log.Fatal(err)
}
fmt.Printf("%#v", resp)
}
Try it in the Go Playground
And you should read this https://golang.org/pkg/encoding/json/

See https://golang.org/pkg/encoding/json
You annotate a struct with JSON fields that should be unmarshalled from the buffer of JSON, something like this:
type AWSObject struct {
Size int `json:"Size"`
Key string `json:"key"`
Owner AWSObjectOwner `json:"Owner"`
}
type AWSObjectOwner struct {
DisplayName `json:"DisplayName"`
}
var awsObjects []AWSObject
err = json.Unmarshal(jsonBuffer, &awsObjects)
if err != nil {
fmt.Printf("Error unmarshaling objects: " + err.Error() + "\n")
...
}

Using quicktype, I generated your model, marshaling code, and usage instructions:
// To parse this JSON data, add this code to your project and do:
//
// r, err := UnmarshalListObjectsResponse(bytes)
// bytes, err = r.Marshal()
package main
import "encoding/json"
func UnmarshalListObjectsResponse(data []byte) (ListObjectsResponse, error) {
var r ListObjectsResponse
err := json.Unmarshal(data, &r)
return r, err
}
func (r *ListObjectsResponse) Marshal() ([]byte, error) {
return json.Marshal(r)
}
type ListObjectsResponse struct {
Contents []Content `json:"Contents"`
IsTruncated bool `json:"IsTruncated"`
Marker string `json:"Marker"`
MaxKeys int64 `json:"MaxKeys"`
Name string `json:"Name"`
Prefix string `json:"Prefix"`
}
type Content struct {
ETag string `json:"ETag"`
Key string `json:"Key"`
LastModified string `json:"LastModified"`
Owner Owner `json:"Owner"`
Size int64 `json:"Size"`
StorageClass string `json:"StorageClass"`
}
type Owner struct {
DisplayName string `json:"DisplayName"`
ID string `json:"ID"`
}
As others suggested, it's probably best to use the AWS SDK for Go, but this method may be useful in general the next time you need to parse arbitrary JSON.

Related

How to struct array in nested json object with the same keys

I am creating host objects in Zabbix via microservices in Golang. I have to serve the following json to
the Zabbix api to create host which is part of multiple groups
{
"jsonrpc": "2.0",
"method": "host.create",
"params": {
"host": "TEST-HOST",
"interfaces": [
{
"type": 2,
"main": 1,
"useip": 1,
"ip": "0.0.0.0",
"dns": "",
"port": "10050"
}
],
"groups": [
{
"groupid": "33"
},
{
"groupid": "27"
}
],
"templates": [
{
"templateid": "12156"
}
],
"inventory_mode": 0
},
"auth": "example_token",
"id": 1
}
This code returns the json object where the groups array is empty.
package main
import (
"bytes"
"encoding/json"
"fmt"
)
type Zabbix struct {
Jsonrpc string `json:"jsonrpc"`
Method string `json:"method"`
Params Params `json:"params"`
Auth string `json:"auth"`
ID int `json:"id"`
}
type Groups struct {
Groupid string `json:"groupid"`
Groupid1 string `json:"groupid"`
}
type Templates struct {
Templateid string `json:"templateid"`
}
type Inventory struct {
Type string `json:"type"`
Tag string `json:"tag"`
TypeFull string `json:"type_full"`
MacaddressA string `json:"macaddress_a"`
MacaddressB string `json:"macaddress_b"`
SerialA string `json:"serialno_a"`
SerialB string `json:"serialno_b"`
}
type Params struct {
Host string `json:"host"`
Interfaces []Interfaces `json:"interfaces"`
Groups []Groups `json:"groups"`
Templates []Templates `json:"templates"`
InventoryMode int `json:"inventory_mode"`
Inventory Inventory `json:"inventory"`
}
type Interfaces struct {
Type int `json:"type"`
Main int `json:"main"`
Useip int `json:"useip"`
IP string `json:"ip"`
DNS string `json:"dns"`
Port string `json:"port"`
}
func main() {
jsonobj := &Zabbix{
Jsonrpc: "2.0",
Method: "host.create",
Params: Params{
Host: "OBU_TEST_123",
Interfaces: []Interfaces{
{
Type: 2,
Main: 1,
Useip: 1,
IP: "10.10.10.10",
DNS: "",
Port: "10050",
},
},
Groups: []Groups{
{
Groupid: "27",
Groupid1: "33",
},
},
Templates: []Templates{
{
Templateid: "12156",
},
},
Inventory: Inventory{
Type: "On Board Unit",
Tag: "test",
TypeFull: "test",
MacaddressA: "test",
MacaddressB: "test",
SerialA: "test",
SerialB: "test",
},
InventoryMode: 0,
},
Auth: "test-token",
ID: 1,
}
byteArray, err := json.Marshal(jsonobj)
if err != nil {
panic(err)
}
fmt.Print(bytes.NewBuffer(byteArray).String())
}
The output:
{
"jsonrpc": "2.0",
"method": "host.create",
"params": {
"host": "OBU_TEST_123",
"interfaces": [
{
"type": 2,
"main": 1,
"useip": 1,
"ip": "10.10.10.10",
"dns": "",
"port": "10050"
}
],
"groups": [
{}
],
"templates": [
{
"templateid": "12156"
}
],
"inventory_mode": 0,
"inventory": {
"type": "On Board Unit",
"tag": "test",
"type_full": "test",
"macaddress_a": "test",
"macaddress_b": "test",
"serialno_a": "test",
"serialno_b": "test"
}
},
"auth": "test-token",
"id": 1
}
What i am missing? Is there any more elegant way to create such a big json object instead of using structs?
type Groups struct {
Groupid string json:"groupid"
Groupid1 string json:"groupid"
}
groupid - Cannot be the same value for both. Change it as follows and it should work.
type Groups struct {
Groupid string json:"groupid"
Groupid1 string json:"groupid1"
}
type Groups struct {
Groupid string `json:"groupid"`
Groupid1 string `json:"groupid"`
}
groupid - Cannot be the same value for both. Change it as follows and it should work.
type Groups struct {
Groupid string `json:"groupid"`
Groupid1 string `json:"groupid1"`
}

Fill struct dynamically from parameters

I've the following struct which works as expected Im getting
data and I was able
type Service struct {
Resources []struct {
Model struct {
Name string `json:"name"`
Credentials struct {
path string `json:"path"`
Vts struct {
user string `json:"user"`
id string `json:"id"`
address string `json:"address"`
} `json:"vts"`
} `json:"credentials"`
} `json:"model"`
} `json:"resources"`
}
service:= Service{}
err := json.Unmarshal([]byte(data), &service
The data is like following,
service1
{
"resources": [
"model": {
"name": "cred",
"credentials": {
"path": "path in fs",
"vts": {
"user": "stephane",
"id": "123",
"address": "some address"
}
},
}
},
Now some services providing additional data under vts for example now we have 3 fields (user/id/address) but some services (service1) can provides additional data like email, secondName ,etc . but the big problem here is that
I need to get it from parameters since (service 2) education, salary etc
Service2
{
"resources": [
"model": {
"name": "cred",
"credentials": {
"path": "path in fs",
"vts": {
"user": "stephane",
"id": "123",
"address": "some address",
"email" : "some email",
"secondName" : "secondName"
}
},
}
},
service N
{
"resources": [
"model": {
"name": "cred",
"credentials": {
"path": "path in fs",
"vts": {
"user": "stephane",
"id": "123",
"address": "some address",
"salary" : "1000000"
}
},
}
},
Of course If I know in advance the fields I can put them all in the struct and use omitempty but I dont know, I just get it as parameter to the function (the new properties names) , some service can provide 10 more fields in this struct (which I should get the properties name of them as args[]to the functions) but I don't know them in advance, this should be dynamic somehow ....is there a nice way to handle it in Golang ?
If you don't know the fields in advance, then don't use a struct but something that is also "dynamic": a map.
type Service struct {
Resources []struct {
Model struct {
Name string `json:"name"`
Credentials struct {
Path string `json:"path"`
Vts map[string]interface{} `json:"vts"`
} `json:"credentials"`
} `json:"model"`
} `json:"resources"`
}
map[sting]interface{} can hold values of any type. If you know all fields will hold a string value, you may also use a map[string]string so it will be easier to work with it.
Example with input JSON:
{
"resources": [
{
"model": {
"name": "cred",
"credentials": {
"path": "path in fs",
"vts": {
"user": "stephane",
"id": "123",
"address": "some address",
"dyn1": "d1value",
"dyn2": "d2value"
}
}
}
}
]
}
Testing it:
service := Service{}
err := json.Unmarshal([]byte(data), &service)
fmt.Printf("%q %v", service, err)
Output (try it on the Go Playground):
{[{{"cred" {"path in fs" map["dyn2":"d2value" "user":"stephane" "id":"123"
"address":"some address" "dyn1":"d1value"]}}}]} <nil>
Now if you want to collect values from the Vts map for a set of keys, this is how you can do it:
args := []string{"dyn1", "dyn2"}
values := make([]interface{}, len(args))
for i, arg := range args {
values[i] = service.Resources[0].Model.Credentials.Vts[arg]
}
fmt.Println(values)
Output of the above will be (try it on the Go Playground):
[d1value d2value]

Why can this data not be properly unmarshalled into my object model?

I have a (non)working example here: https://play.golang.org/p/qaYhKvJ65J3
I'm not sure why the following data:
alertData := `{
"Id": 0,
"Version": 0,
"OrgId": 1,
"DashboardId": 61,
"PanelId": 84,
"Name": "{qa-dev}{stats-pipeline} Topology Message Age (aggregator) alert",
"Message": "",
"Severity": "",
"State": "",
"Handler": 1,
"Silenced": false,
"ExecutionError": "",
"Frequency": 10,
"EvalData": null,
"NewStateDate": "0001-01-01T00:00:00Z",
"PrevStateDate": "0001-01-01T00:00:00Z",
"StateChanges": 0,
"Created": "0001-01-01T00:00:00Z",
"Updated": "0001-01-01T00:00:00Z",
"Settings": {
"conditions": [
{
"evaluator": {
"params": [
10000
],
"type": "gt"
},
"operator": {
"type": "and"
},
"query": {
"datasourceId": 2,
"model": {
"hide": true,
"refCount": 0,
"refId": "C",
"textEditor": false
},
"params": [
"C",
"5m",
"now"
]
},
"reducer": {
"params": [],
"type": "avg"
},
"type": "query"
}
],
"executionErrorState": "keep_state",
"frequency": "10s",
"handler": 1,
"name": "{qa-dev}{stats-pipeline} Topology Message Age (aggregator) alert",
"noDataState": "keep_state",
"notifications": []
}
}`
Can't be unmarshalled into the following object model:
type Condition struct {
Evaluator struct {
Params []int `json:"params"`
Type string `json:"type"`
} `json:"evaluator"`
Operator struct {
Type string `json:"type"`
} `json:"operator"`
Query struct {
Params []string `json:"params"`
} `json:"query"`
Reducer struct {
Params []interface{} `json:"params"`
Type string `json:"type"`
} `json:"reducer"`
Type string `json:"type"`
}
When I do the following:
condition := Condition{}
err := json.Unmarshal([]byte(alertData), &condition)
if err != nil {
panic(err)
}
fmt.Printf("\n\n json object:::: %+v", condition)
I just get: json object:::: {Evaluator:{Params:[] Type:} Operator:{Type:} Query:{Params:[]} Reducer:{Params:[] Type:} Type:}
Ideally I'd be able to parse it into something like type Conditions []struct{ } but I'm not sure if you can define models as lists?
It looks like you are trying to access the "conditions" property nested under the root "Settings" property. As such, you need to define that root-level type and enough fields to tell the unmarshaler how to find your target property. As such, you would just need to create a new "AlertData" type with the necessary "Settings/conditions" fields.
For example (Go Playground):
type AlertData struct {
Settings struct {
Conditions []Condition `json:"conditions"`
}
}
func main() {
alert := AlertData{}
err := json.Unmarshal([]byte(alertData), &alert)
if err != nil {
panic(err)
}
fmt.Printf("OK: conditions=%#v\n", alert.Settings.Conditions)
// OK: conditions=[]main.Condition{main.Condition{Evaluator:struct { Params []int "json:\"params\""; Type string "json:\"type\"" }{Params:[]int{10000}, Type:"gt"}, Operator:struct { Type string "json:\"type\"" }{Type:"and"}, Query:struct { Params []string "json:\"params\"" }{Params:[]string{"C", "5m", "now"}}, Reducer:struct { Params []interface {} "json:\"params\""; Type string "json:\"type\"" }{Params:[]interface {}{}, Type:"avg"}, Type:"query"}}
}
Note that the printed listing includes so much type information because the "Condition" type uses anonymous structs as field types. If you were to extract them into named structs it will be easier to work with the data, e.g.:
type Condition struct {
Evaluator Evaluator `json:"evaluator"`
Operator Operator `json:"operator"`
// ...
}
type Evaluator struct {
Params []int `json:"params"`
Type string `json:"type"`
}
type Operator struct {
Type string `json:"type"`
}
//...
// OK: conditions=[]main.Condition{
// main.Condition{
// Evaluator:main.Evaluator{Params:[]int{10000}, Type:"gt"},
// Operator:main.Operator{Type:"and"},
// Query:main.Query{Params:[]string{"C", "5m", "now"}},
// Reducer:main.Reducer{Params:[]interface {}{}, Type:"avg"},
// Type:"query",
// },
// }
Go Playground example here...
Maerics explanation is correct, here is an alternative approach which wraps access around struct methods, the data structure is also fully defined. If you're new to Go it's good to get handle on creating the data structures yourself, but here is a handy utility for helping create structs from valid JSON
https://mholt.github.io/json-to-go/
package main
import (
"encoding/json"
"fmt"
"log"
"time"
)
type Data struct {
ID int `json:"Id"`
Version int `json:"Version"`
OrgID int `json:"OrgId"`
DashboardID int `json:"DashboardId"`
PanelID int `json:"PanelId"`
Name string `json:"Name"`
Message string `json:"Message"`
Severity string `json:"Severity"`
State string `json:"State"`
Handler int `json:"Handler"`
Silenced bool `json:"Silenced"`
ExecutionError string `json:"ExecutionError"`
Frequency int `json:"Frequency"`
EvalData interface{} `json:"EvalData"`
NewStateDate time.Time `json:"NewStateDate"`
PrevStateDate time.Time `json:"PrevStateDate"`
StateChanges int `json:"StateChanges"`
Created time.Time `json:"Created"`
Updated time.Time `json:"Updated"`
Settings struct {
Conditions []Condition `json:"conditions"`
ExecutionErrorState string `json:"executionErrorState"`
Frequency string `json:"frequency"`
Handler int `json:"handler"`
Name string `json:"name"`
NoDataState string `json:"noDataState"`
Notifications []interface{} `json:"notifications"`
} `json:"Settings"`
}
type Condition struct {
Evaluator struct {
Params []int `json:"params"`
Type string `json:"type"`
} `json:"evaluator"`
Operator struct {
Type string `json:"type"`
} `json:"operator"`
Query struct {
DatasourceID int `json:"datasourceId"`
Model struct {
Hide bool `json:"hide"`
RefCount int `json:"refCount"`
RefID string `json:"refId"`
TextEditor bool `json:"textEditor"`
} `json:"model"`
Params []string `json:"params"`
} `json:"query"`
Reducer struct {
Params []interface{} `json:"params"`
Type string `json:"type"`
} `json:"reducer"`
Type string `json:"type"`
}
func (d Data) GetFirstCondition() (Condition, error) {
if len(d.Settings.Conditions) > 0 {
return d.Settings.Conditions[0], nil
}
return Condition{}, fmt.Errorf("no conditions found")
}
func (d Data) GetConditionByIndex(index uint) (Condition, error) {
if len(d.Settings.Conditions) == 0 {
return Condition{}, fmt.Errorf("no conditions found")
}
if int(index) > len(d.Settings.Conditions)-1 {
return Condition{}, fmt.Errorf("index out of bounds")
}
return d.Settings.Conditions[index], nil
}
var alertData = `{
"Id": 0,
"Version": 0,
"OrgId": 1,
"DashboardId": 61,
"PanelId": 84,
"Name": "{qa-dev}{stats-pipeline} Topology Message Age (aggregator) alert",
"Message": "",
"Severity": "",
"State": "",
"Handler": 1,
"Silenced": false,
"ExecutionError": "",
"Frequency": 10,
"EvalData": null,
"NewStateDate": "0001-01-01T00:00:00Z",
"PrevStateDate": "0001-01-01T00:00:00Z",
"StateChanges": 0,
"Created": "0001-01-01T00:00:00Z",
"Updated": "0001-01-01T00:00:00Z",
"Settings": {
"conditions": [
{
"evaluator": {
"params": [
10000
],
"type": "gt"
},
"operator": {
"type": "and"
},
"query": {
"datasourceId": 2,
"model": {
"hide": true,
"refCount": 0,
"refId": "C",
"textEditor": false
},
"params": [
"C",
"5m",
"now"
]
},
"reducer": {
"params": [],
"type": "avg"
},
"type": "query"
}
],
"executionErrorState": "keep_state",
"frequency": "10s",
"handler": 1,
"name": "{qa-dev}{stats-pipeline} Topology Message Age (aggregator) alert",
"noDataState": "keep_state",
"notifications": []
}
}`
func main() {
var res Data
err := json.Unmarshal([]byte(alertData), &res)
if err != nil {
log.Fatal(err)
}
fmt.Println(res.GetFirstCondition())
fmt.Println(res.GetConditionByIndex(0))
// should fail :-)
fmt.Println(res.GetConditionByIndex(1))
}

How to create custom key in json response using golang

I get a following json response through golang.
[
{
"CreatedOn": "03-22-2015",
"JSONReceived": [
{
"EzpOrderID": "ezp_126",
"FirstName": "Kumar",
"LastName": "S",
"OrderDesc": "Sample"
}
],
"Status": "0",
"id": "80acbdad-8aae-4d6c-ac63-2a02a9db64b4"
},
{
"CreatedOn": "03-22-2015",
"JSONReceived": [
{
"EzpOrderID": "ezp_126",
"FirstName": "Vasanth",
"LastName": "K",
"OrderDesc": "Sample"
}
],
"Status": "0",
"id": "8f7f52a5-793a-45bd-a9b7-ed41495e0ee3"
}
]..
But i need to create with key in response. sample response as follows. How to achieve using golang programming.
{
"returnResponseData": [{
"CreatedOn": "03-22-2015",
"JSONReceived": [{
"EzpOrderID": "ezp_126",
"FirstName": "Kumar",
"LastName": "S",
"OrderDesc": "Sample"
}],
"Status": "0",
"id": "80acbdad-8aae-4d6c-ac63-2a02a9db64b4"
}, {
"CreatedOn": "03-22-2015",
"JSONReceived": [{
"EzpOrderID": "ezp_126",
"FirstName": "Vasanth",
"LastName": "K",
"OrderDesc": "Sample"
}],
"Status": "0",
"id": "8f7f52a5-793a-45bd-a9b7-ed41495e0ee3"
}]
}
Please help me to achieve this task using golang.
Whole Source code as follows:
func orderList(w http.ResponseWriter, request *http.Request) {
rows, err := r.Table("orders").Run(session)
if err != nil {
fmt.Println(err)
return
}
var resultSet []interface{}
err = rows.All(&resultSet)
if err != nil {
fmt.Printf("Error scanning database result: %s", err)
return
}
if origin := request.Header.Get("Origin"); origin != "" {
w.Header().Set("Access-Control-Allow-Origin", origin)
w.Header().Set("Access-Control-Allow-Methods", "GET")
w.Header().Set("Access-Control-Allow-Headers",
"Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(200)
json.NewEncoder(w).Encode(resultSet)
}
You have to define another type like this:
type Wrapper struct {
ReturnResponseData []interface{} `json:"returnResponseData"`
}
and then encode wrapper, containing your response set:
json.NewEncoder(w).Encode(&Wrapper{ReturnResponseData: resultSet})
Notice, that you have to use property tag to achieve the name "returnResponseData", starting of a small letter (because encoder doesn't encode private properties by default).

Get Inner JSON Value in Go

Simple question that I'm having a difficult time how to structure a struct for JSON decoding.
How can I copy an inner field of a struct to another field of a struct?
I have JSON
{
"Trains": [{
"Car": "6",
"Destination": "SilvrSpg",
"DestinationCode": "B08",
"DestinationName": "Silver Spring",
"Group": "1",
"Line": "RD",
"LocationCode": "A13",
"LocationName": "Twinbrook",
"Min": "1"
}]
}
And I have structs
type Trains struct {
Min string `json:"Min"`
DestName string `json:"DestinationName"`
DestCode string `json:"DestinationCode"`
LocName string `json:"LocationName"`
LocCode string `json:"LocationCode"`
Line string `json:"Line"`
}
type AllData struct {
Data []Trains `json:"Trains"`
}
How Can I get the value of the Trains.LocationCode to a struct like
type AllData struct {
Id Trains[0].LocCode value
Data []Trains `json:"Trains"`
}
So I basically just need to have JSON like this
{
"Id":"A13",
"Data": [{
"Car": "6",
"Destination": "SilvrSpg",
"DestinationCode": "B08",
"DestinationName": "Silver Spring",
"Group": "1",
"Line": "RD",
"LocationCode": "A13",
"LocationName": "Twinbrook",
"Min": "1"
}]
}
Where the Id is the inner value of the Trains struct.
How can I structure a struct to reflect this?
The JSON decoder does not have this capability. You must write the line of code in your application.
package main
import (
"encoding/json"
"fmt"
"log"
)
var s = `
{
"Trains": [{
"Car": "6",
"Destination": "SilvrSpg",
"DestinationCode": "B08",
"DestinationName": "Silver Spring",
"Group": "1",
"Line": "RD",
"LocationCode": "A13",
"LocationName": "Twinbrook",
"Min": "1"
}]
}`
type Train struct {
Min string `json:"Min"`
DestName string `json:"DestinationName"`
DestCode string `json:"DestinationCode"`
LocName string `json:"LocationName"`
LocCode string `json:"LocationCode"`
Line string `json:"Line"`
}
type Data struct {
// The name "-" tells the JSON decoder to ignore this field.
ID string `json:"-"`
Trains []Train
}
func main() {
var d Data
if err := json.Unmarshal([]byte(s), &d); err != nil {
log.Fatal(err)
}
if len(d.Trains) < 1 {
log.Fatal("No trains")
}
// Copy value from inner to outer.
d.ID = d.Trains[0].LocCode
fmt.Printf("%+v\n", &d)
}