Recieving a EOF Panic error - go

I'm trying to decode a json I get. Here's an example json I get:
{"response":"1","number":"1234","id":nil}
Here's my struct:
type AutoGenerated struct {
Response string `json:"response"`
Number string `json:"number"`
ID interface{} `json:"id"`
}
I use the decode function in encode/json. What Am I getting wrong? ID has the chance to be both a string or a nil value.
Here's me exact error incase it helps.
panic: EOF

Without you showing how you're doing it, I think the best answer is to show you how to do it.
package main
import (
"fmt"
"log"
"encoding/json"
)
func main() {
j := []byte(`{"response":"1","number":"1234","id":null}`)
data := AutoGenerated{}
err := json.Unmarshal(j, &data)
if err != nil {
log.Println(err.Error())
return
}
fmt.Println(data)
}
type AutoGenerated struct {
Response string `json:"response"`
Number string `json:"number"`
ID interface{} `json:"id"`
}

The JSON string you put here is invalid. You can find this code sample for reference.
If you're going to set the id field to nil, just don't put it in the JSON string.
package main
import (
"encoding/json"
"fmt"
"io"
"log"
"strings"
)
type AutoGenerated struct {
Response string `json:"response"`
Number string `json:"number"`
ID interface{} `json:"id"`
}
func main() {
jsonStream := `
{ "response": "1", "number": "1234" }
{ "response": "1", "number": "1234", "id": "nil" }
`
decoder := json.NewDecoder(strings.NewReader(jsonStream))
for {
var m AutoGenerated
if err := decoder.Decode(&m); err == io.EOF {
break
} else if err != nil {
log.Fatal(err)
}
fmt.Println(m)
}
}
The output of the program is:
{1 1234 <nil>}
{1 1234 nil}

Related

How to extract data from map[string]interface{}?

I am sending the data to the API like following:
{"after": {"amount": 811,"id":123,"status":"Hi"}, "key": [70]}
and i am getting following while printing :
map[after:map[amount:811 id:123 status:Hi ] key:[70]]
Is there any way to print individual field like this??
amount::800
id:123
status:Hi
The code:
package main
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"strings"
)
var (
PORT = ":8080"
)
func main() {
fmt.Println("In Main")
http.HandleFunc("/", changedData)
http.ListenAndServe(PORT, nil)
}
type Data struct {
Id int64 `json:"id"`
Amount float64 `json:"amount"`
Status string `json:"status"`
}
type mark map[string]interface{}
func changedData(w http.ResponseWriter, r *http.Request) {
fmt.Println("Coming From API")
reqBody, _ := ioutil.ReadAll(r.Body)
fmt.Println("Data coming from API ", string(reqBody))
digit := json.NewDecoder(strings.NewReader(string(reqBody)))
for digit.More() {
var result mark
err := digit.Decode(&result)
if err != nil {
if err != io.EOF {
log.Fatal(err)
}
break
}
fmt.Println("final_data ", result)
}
}
Decode to a Go type that matches the structure of the JSON document. You declared a type for the "after" field. Wrap that type with a struct to match the document.
func changedData(w http.ResponseWriter, r *http.Request) {
var v struct{ After Data }
err := json.NewDecoder(r.Body).Decode(&v)
if err != nil {
http.Error(w, "bad request", 400)
return
}
fmt.Printf("final_data: %#v", v.After)
}
Playground example.
I think you can define a struct type if you know the JSON file format or if the JSON format is predefined. As far as I know that mostly using interface{} is a way when you don't know the JSON format or there is no predefined format of the JSON. If you define a struct type  and use it while unmarshaling the JSON to struct, you can access the variables by typing like data.Id or data.Status.
Here's an example code:
package main
import (
"encoding/json"
"fmt"
)
type Data struct {
AfterData After `json:"after"`
Key []int `json:"key"`
}
type After struct {
Id int64 `json:"id"`
Amount float64 `json:"amount"`
Status string `json:"status"`
}
func main() {
j := []byte(`{"after": {"amount": 811,"id":123,"status":"Hi"}, "key": [70]}`)
var data *Data
err := json.Unmarshal(j, &data)
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Println(data.AfterData)
fmt.Println(data.AfterData.Id)
fmt.Println(data.AfterData.Amount)
fmt.Println(data.AfterData.Status)
}
Output will be
{123 811 Hi}
123
811
Hi
Go Playground

Reading and Unmarshalling API results in Golang

In the below program I'm extracting some data from an API.
It outputs a rather complex data.
When I ioutil.ReadAll(resp.Body), the result is of type []uint8.
If I try to read the results, its just a random array of integers.
However, I'm able to read it if I convert it to string using string(diskinfo)
But I want to use this in a Struct and having trouble unmarshalling.
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"reflect"
)
type ApiResults struct {
results []struct {
statement_id int `json.statement_id`
series []struct {
name string `json.name`
tags struct {
host string `json.host`
}
columns []string `json.columns`
values []interface{} `json.values`
}
}
}
func main() {
my_url := "my_url"
my_qry := fmt.Sprintf("my_query")
resp, err := http.Get(my_url + url.QueryEscape(my_qry))
if err != nil {
fmt.Printf("ERROR: %v\n", err)
} else {
fmt.Println(reflect.TypeOf(resp))
diskinfo, _ := ioutil.ReadAll(resp.Body)
fmt.Println(reflect.TypeOf((diskinfo)))
fmt.Println(diskinfo)
fmt.Println(string(diskinfo))
diskinfo_string := string(diskinfo)
data := ApiResults{}
json.Unmarshal([]byte(diskinfo_string), &data)
//fmt.Printf("Values = %v\n", data.results.series.values)
//fmt.Printf("Server = %v\n", data.results.series.tags.host)
}
}
If I view the data as a string, I get this (formatted):
{"results":[
{"statement_id":0,
"series":[
{"name":"disk",
"tags":{"host":"myServer1"},
"columns":["time","disk_size"],
"values":[["2021-07-07T07:53:32.291490387Z",1044]]},
{"name":"disk",
"tags":{"host":"myServer2"},
"columns":["time","disk_size"],
"values":[["2021-07-07T07:53:32.291490387Z",1046]]}
]}
]}
I think my Apireturn struct is also structured incorrectly because the API results have info for multiple hosts.
But first, I doubt if the data has to be sent in a different format to the struct. Once I do this, I can probably try to figure out how to read from the Struct next.
The ioutil.ReadAll already provides you the data in the type byte[]. Therefore you can just call json.Unmarshal passing it as a parameter.
import (
"encoding/json"
"io/ioutil"
"net/http"
)
func toStruct(res *http.Response) (*ApiResults, error) {
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}
defer res.Body.Close()
data := ApiResults{}
if err := json.Unmarshal(body, &data); err != nil {
return nil, err
}
return data, nil
}
There also seems to be an issue with your struct. The correct way to use struct tags is as follows. Plus, fields need to be exported for the json tag (used by json.Umarshal) to work – starting with uppercase will do it.
type ApiResults struct {
Results []struct {
StatementId int `json:"statement_id"`
Series []struct {
Name string `json:"name"`
Tags struct {
Host string `json:"host"`
} `json:"tags"`
Columns []string `json:"columns"`
Values []interface{} `json:"values"`
} `json:"series"`
} `json:"results"`
}

Why is json values empty

Can you see why json values dont get saved:
Update: And if you would like to explain why this is downgraded as "Off topic"?
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
)
type UsedInContext struct {
UsedIn string `json:"usedin"`
ContextName string `json:"contextname"`
}
type ContextData struct {
usedInContext []UsedInContext `json:"usedincontext"`
}
func saveData() {
var jsonBlob = []byte(`{
"usedincontext":
[
{"usedin":"local", "contextname":"desktop"}
]
}`)
usedInContext := UsedInContext{}
err := json.Unmarshal(jsonBlob, &usedInContext)
if err != nil {
}
usedInContextJson, _ := json.Marshal(usedInContext)
err = ioutil.WriteFile("data.json", usedInContextJson, 0644)
fmt.Printf("%+v", usedInContext)
}
I get the following:
{"usedin":"","contextname":""}
You unmarshal your document to the type UsedInContext, while it matches the schema for ContextData:
type ContextData struct {
UsedInContext []UsedInContext `json:"usedincontext"` // exported
}
var data ContextData
json.Unmarshal(jsonBlob, &data)
fmt.Printf("%+v", data)

Consume a nested array inside JSON request in Go

How do I go about consuming the following json post in Go?
{
"notificationType": "email",
"client": "The CLient",
"content": "Hellow World",
"recipients": [
{
"address": "email1#example.com"
},
{
"address": "email2#example.com"
}
]
}
I've managed to get the string types but I really don't know enough about Go to deal with the recipients array.
My code looks like this:
package handlers
import (
"net/http"
"encoding/json"
"notificationservice/src/validation"
"io/ioutil"
"fmt"
)
func EmailHandler(w http.ResponseWriter, r *http.Request) {
b, err := ioutil.ReadAll(r.Body)
defer r.Body.Close()
if err != nil {
http.Error(w, err.Error(), 500)
return
}
var postData validation.EmailValidator
err = json.Unmarshal(b, &postData)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
fmt.Println(postData.Client)
fmt.Println(postData.Content)
}
My struct:
package validation
import "fmt"
type EmailValidator struct {
Client string `json:"client"`
Content string `json:"content"`
//Recipients []string `json:"recipients"`
}
func (validator * EmailValidator) ValidateEmail() (bool) {
var required = []string {validator.Client, validator.Content, validator.Stuff}
for _, param := range required {
fmt.Println(param)
}
return true;
}
I've tried setting Recipients to []string and [][]string but I really don't know what I'm doing.
In PHP I would use the var_dump command to print out the entire object and debug step by step from there, but Go doesn't appear to have that functionality.
You can try something like this:
package main
import (
"encoding/json"
"fmt"
)
type Email struct {
Adress string `json:"address"`
}
type EmailValidator struct {
Client string `json:"client"`
Content string `json:"content"`
Recipients []Email `json:"recipients"`
}
func main() {
j := `{
"notificationType": "email",
"client": "The CLient",
"content": "Hellow World",
"recipients": [
{
"address": "email1#example.com"
},
{
"address": "email2#example.com"
}
]
}`
result := EmailValidator{}
json.Unmarshal([]byte(j), &result)
fmt.Printf("%+v", result) // something like var_dump in PHP
}
You need an array of "things with an address":
type EmailValidator struct {
Client string `json:"client"`
Content string `json:"content"`
Recipients []Recipient `json:"recipients"`
}
type Recipient struct {
Address string `json:"address"`
}
You can nest objects, and Unmarshal will handle the entire tree for you.
type Recipient struct {
Address string `json:"address"`
}
type EmailValidator struct {
Client string `json:"client"`
Content string `json:"content"`
Recipients []Recipient `json:"recipients"`
}
The rest of your code looks good.

Use string as struct value

I have this code. What I need is to get the transaction details from the transaction ID returned from blockchain
package main
import (
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"strings"
)
type Transaction struct {
Bid string `json:"bid"`
Fun string `json:"fun"`
ID string `json:"id"`
Timestamp string `json:"timestamp"`
TraderA string `json:"traderA"`
TraderB string `json:"traderB"`
Seller string `json:"seller"`
PointAmount string `json:"pointAmount"`
PrevTransactionID string `json:"prevTransactionId"`
}
type AllTxs struct {
TXs []Transaction `json:"tx"`
}
type Transact struct {
Cert string `json:"cert"`
ChaincodeID string `json:"chaincodeID"`
Nonce string `json:"nonce"`
Payload string `json:"payload"`
Signature string `json:"signature"`
Timestamp string `json:"nanos"`
Txid string `json:"txid"`
Type int `json:"type"`
}
func main() {
resp, err := http.Get("http://blockchain_transactions_url/trans_id")
if err != nil {
// handle error
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
byteArray := []byte(body)
var t Transact
json.Unmarshal(byteArray, &t)
//I get all the values base64 encoded
st, err := base64.StdEncoding.DecodeString(t.Payload)
if err != nil {
log.Fatal(err)
}
trd := string(st)
sp := strings.Split(trd, "\n")
result := strings.Join(sp, ",")
res := strings.Replace(result, ",", `", "`, -1)
ret := strings.Replace(res, `", "`, `{"`, 1) + `"}`
byteA := []byte(ret)
var tf AllTxs
json.Unmarshal(byteA, &tf)
//the tf...
ref := Transaction{}
fmt.Println(ref.Id)
}
the t.Payload I get is
"CsYBCAESgwESgAE3ZjFhY2Y2MTgxMGRhODMyMTA5NjZiNGYzNjc2NWU5NmIxY2Q0OTliODkyNmY0MDU0YWQ5NzhlNzhkZjczMDRhOGZlMDM1ZjZhYTBhODE2YzdmNjFlNGZkZDQ1MjM4M2Q5ZmU5ZDQxNmIyZGI4YTE1YmRkMjAzZmU2N2I5OTYyZho8ChBpbml0X3RyYW5zYWN0aW9uCgYwMDAxMTcKA2dpbwoEbW9oYQoBNQoCMTIKBTk4NzczCgcyMDE3NDIy"
the tf I get is
{"??7f1acf61810da83210966b4f36765e96b1cd499b8926f4054ad978e78df7304a8fe035f6aa0a816c7f61e4fdd452383d9fe9d416b2db8a15bdd203fe67b9962f<", "init_transaction", "000117", "gio", "moha", "5", "12", "98773", "2017422"}
At the last how can I get the JSON of Transaction/AllTxs type?
Given the comment, it looks like you are trying to unmarshal the string as JSON, but as it stands, the string is not valid JSON; if it were, you would be able to unmarshal it as follows, ignoring the fact that the fields to not appear to match up with the desired structure;
package main
import (
"encoding/json"
"fmt"
)
type Transaction struct {
Bin string `json:"bin"`
Fun string `json:"fun"`
ID string `json:"id"`
Timestamp string `json:"timestamp"`
TraderA string `json:"traderA"`
TraderB string `json:"traderB"`
Seller string `json:"seller"`
PointAmount string `json:"pointAmount"`
PrevTransactionID string `json:"prevTransactionId"`
}
func main() {
snippet := `{
"bin": "7f1acf61810da83210966b4f36765e96b1cd499b8926f4054ad978e78df7304a8fe035f6aa0a816c7f61e4fdd452383d9fe9d416b2db8a15bdd203fe67b9962f",
"fun": "init_transaction",
"id": "000117",
"timestamp": "gio",
"traderA": "moha",
"traderB": "5",
"seller": "12",
"pointAmount": "98773",
"prevTransactionId": "2017422"
}`
t := Transaction{}
json.Unmarshal([]byte(snippet), &t)
fmt.Println(t)
}

Resources