Error with JSON parsing in Golang - json

I develop this code:
package main
import (
"fmt"
"io/ioutil"
"encoding/json"
)
type Client struct{
host string
key string
secrete string
username string
password string
}
type Config struct{
Client []Client
}
func main(){
content, err := ioutil.ReadFile("conf2.json")
if err!=nil{
fmt.Print("Error:",err)
}
var conf Config
err=json.Unmarshal(content, &conf)
if err!=nil{
fmt.Print("Error:",err)
}
json.Unmarshal(content, &conf)
fmt.Println(conf.Client[0].host)
}
to parse and print the first host detail from my json, that looks like this:
{
"Client" :
[
{"host":"192.168.1.2"},
{"key":"abcdf"},
{"secrete":"9F6w"},
{"username":"user"},
{"password":"password"}
]
}
But I got an empty string. Could someone know the reason?

Three things to fix:
json.Unmarshal requires the struct fields to be capitalized to be exported or they are ignored
You need the json:"<name>" specifier after the fields so the unmarshal knows the struct field to json mapping
Your json was making multiple clients with one field filled in instead of one client with all the fields filled in
See example: https://play.golang.org/p/oY7SppWNDC

Here, it is the solution to my problem:
package main
import (
"fmt"
"io/ioutil"
"encoding/json"
)
type Client struct {
Host string `json:"host"`
Key string `json:"apikey"`
Secret string `json:"secret"`
Username string `json:"username"`
Password string `json:"password"`
}
type Config struct {
Client Client `json:"Client"`
}
func main(){
jsonmsg, err := ioutil.ReadFile("conf2.json")
conf := new(Config)
err = json.Unmarshal([]byte(jsonmsg), &conf)
if err != nil {
fmt.Print("Error:", err)
}
fmt.Printf("%+v\n%+v\n%+v\n%+v\n%+v\n", conf.Client.Host, conf.Client.Key, conf.Client.Secret, conf.Client.Username,conf.Client.Password)
}

Related

Why doesn't JSON parsing fail with completely different type passed to Decode()?

I have the following data structures which I'd like to parse from an API:
type OrderBook struct {
Pair string `json:"pair"`
UpdateTime int64 `json:"update_time"`
}
type depthResponse struct {
Result OrderBook `json:"result"`
// doesn't matter here
//Cmd string `json:"-"`
}
and when I parse the following:
data := `{"error":{"code":"3016","msg":"交易对错误"},"cmd":"depth"}`
It doesn't fail. Why?
Full source code (playground)
package main
import (
"encoding/json"
"fmt"
"log"
"strings"
)
type OrderBook struct {
Pair string `json:"pair"`
UpdateTime int64 `json:"update_time"`
}
type depthResponse struct {
Result OrderBook `json:"result"`
}
func main() {
data := `{"error":{"code":"3016","msg":"交易对错误"},"cmd":"depth"}`
r := strings.NewReader(data)
var resp depthResponse
if err := json.NewDecoder(r).Decode(&resp); err != nil {
log.Fatalf("We should end up here: %v", err)
}
fmt.Printf("%+v\n", resp)
}
That's the expected behaviour of Decode (as documented in the Unmarshal function):
https://golang.org/pkg/encoding/json/#Unmarshal
By default, object keys which don't have a corresponding struct field are ignored.
You can however use the DisallowUnknownFields() function (as described in the docs as well) to have it fail if the input JSON has fields not contained in the destination struct.
dec := json.NewDecoder(r)
dec.DisallowUnknownFields()
In that case, you'll get an error as you expect.
Modified playground here: https://play.golang.org/p/A0f6dxTXV34

Golang json decoding returns empty [duplicate]

This question already has answers here:
JSON and dealing with unexported fields
(2 answers)
Closed 4 years ago.
Can some one please explain to me why this code fail to decode json properly:
package main
import (
"fmt"
"os"
"log"
"encoding/json"
)
type Config struct {
mongoConnectionString string `json:"database"`
Elastic struct{
main string `json:"main"`
log string `json:"log"`
} `json:"elastic"`
logFilePath string `json:"logfile"`
}
func main(){
loadConfiguration("./config.json")
}
func loadConfiguration(file string){
var configuration Config
configFile, err := os.Open(file); if err != nil {
log.Panic("Could not open", file)
}
defer configFile.Close()
if err := json.NewDecoder(configFile).Decode(&configuration); err != nil {
log.Panic("./config.json is currupted")
}
fmt.Print(configuration.logFilePath)
}
Json data:
{
"database": "localhost",
"elastic": {
"main": "test",
"log": "test"
},
"logfile": "./logs/log.log"
}
The execution of this program will result in empty configuration.logFilePath
What am i missing?
Thanks
For the json package to properly decode from json in go, fields must be exported (capitalized) within the struct definition.
Changing Config to:
type Config struct {
MongoConnectionString string `json:"database"`
Elastic struct{
Main string `json:"main"`
Log string `json:"log"`
} `json:"elastic"`
LogFilePath string `json:"logfile"`
}
will make all fields deserialize correctly.

How to unmarshal json in golang when left part is a number

I'd like to unmarshal a json like this in the code. But this code doesn't work. Any suggestions? Thx!
PS. playground here http://play.golang.org/p/m2f94LY_d_
package main
import "encoding/json"
import "fmt"
type Response struct {
Page int
One string "1"
}
func main() {
in := []byte(`{"page":1, "1":"this is 1"}`)
res := &Response{}
json.Unmarshal(in, &res)
fmt.Println(res)
}
You need to tell the json library what the json field names are:
type Response struct {
Page int `json:"page"`
One string `json:"1"`
}
Live: http://play.golang.org/p/CNcvQMqBGD

Marshall and UnMarshall JSON Content in GoLang

I have a sample json file which is structured like this
{
"method":"brute_force",
"bc":"select * from blah;",
"gc":[
"select sum(year) from blah;",
"select count(*) from table;"
]
}
I am trying to write a go program which can read this file and operate of json content.
package main
import (
"fmt"
"encoding/json"
"io/ioutil"
)
type Response2 struct {
method string
bc string
gc []string
}
func main() {
file,_ := ioutil.ReadFile("config.json")
fmt.Printf("%s",string(file))
res := &Response2{}
json.Unmarshal([]byte(string(file)), &res)
fmt.Println(res)
fmt.Println(res.method)
fmt.Println(res.gc)
}
res.method and res.gc dont print anything. I have no idea on whats going wrong.
type Response2 struct {
method string
bc string
gc []string
}
The name of the fields Must be Uppercase otherwise the Json module can't access them (they are private to your module).
You can use the json tag to specify a match between Field and name
type Response2 struct {
Method string `json:"method"`
Bc string `json:"bc"`
Gc []string `json:"gc"`
}

Converting Go struct to JSON

I am trying to convert a Go struct to JSON using the json package but all I get is {}. I am certain it is something totally obvious but I don't see it.
package main
import (
"fmt"
"encoding/json"
)
type User struct {
name string
}
func main() {
user := &User{name:"Frank"}
b, err := json.Marshal(user)
if err != nil {
fmt.Printf("Error: %s", err)
return;
}
fmt.Println(string(b))
}
Then when I try to run it I get this:
$ 6g test.go && 6l -o test test.6 && ./test
{}
You need to export the User.name field so that the json package can see it. Rename the name field to Name.
package main
import (
"fmt"
"encoding/json"
)
type User struct {
Name string
}
func main() {
user := &User{Name: "Frank"}
b, err := json.Marshal(user)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(b))
}
Output:
{"Name":"Frank"}
Related issue:
I was having trouble converting struct to JSON, sending it as response from Golang, then, later catch the same in JavaScript via Ajax.
Wasted a lot of time, so posting solution here.
In Go:
// web server
type Foo struct {
Number int `json:"number"`
Title string `json:"title"`
}
foo_marshalled, err := json.Marshal(Foo{Number: 1, Title: "test"})
fmt.Fprint(w, string(foo_marshalled)) // write response to ResponseWriter (w)
In JavaScript:
// web call & receive in "data", thru Ajax/ other
var Foo = JSON.parse(data);
console.log("number: " + Foo.number);
console.log("title: " + Foo.title);
This is an interesting question, it is very easy using the new go versions. You should do this:
package main
import (
"fmt"
"encoding/json"
)
type User struct {
Name string `json:"name"`
}
func main() {
user := &User{name:"Frank"}
b, err := json.Marshal(user)
if err != nil {
fmt.Printf("Error: %s", err)
return;
}
fmt.Println(string(b))
}
Change this name to Name.
You can define your own custom MarshalJSON and UnmarshalJSON methods and intentionally control what should be included, ex:
package main
import (
"fmt"
"encoding/json"
)
type User struct {
name string
}
func (u *User) MarshalJSON() ([]byte, error) {
return json.Marshal(&struct {
Name string `json:"name"`
}{
Name: "customized" + u.name,
})
}
func main() {
user := &User{name: "Frank"}
b, err := json.Marshal(user)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(b))
}
Struct values encode as JSON objects. Each exported struct field becomes
a member of the object unless:
the field's tag is "-", or
the field is empty and its tag specifies the "omitempty" option.
The empty values are false, 0, any nil pointer or interface value, and any array, slice, map, or string of length zero. The object's default key string is the struct field name but can be specified in the struct field's tag value. The "json" key in the struct field's tag value is the key name, followed by an optional comma and options.