Parse JSON with field name containing underscore - json

So I have JSON like this
{"Name":"Jame","Age":6,"Original_Name":"Jameson"}
In order to get "Name" and "Age" in Go, I just need to use a corresponding struct
type Result struct {
Name string
Age int
}
But how do I get the field "Original_Name" since I cannot use underscore in go?

Does this work:
type Result struct {
Name string
Age int
Originalname string `json:"Original_Name"`
}

Related

Unmarshaling JSON into struct but converting values into required dtypes

I am using a JSON API for which I have to parse it into a struct. However, the API returns all values, even numbers, as strings and I need them to be in the format of numbers. So currently, I have a struct which has member fields which are all strings and after I have parsed the data, I loop through the entries to convert the values and add them to a new struct which has the specific entries in float or int values.
Is there any way to do the parsing and do type conversion in one go without having to use an intermediary struct representation from which to convert the values into the desired data types?
Example Code
str := []byte(`
{
"name": "Jim Burnham",
"age": "34",
"dob_day": "22",
"dob_month": "3",
"dob_year": "1984"
}
`)
Here is a sample JSON declaration of a response from an API. Notice how the age, day, month and year are returned as strings rather than integers. Now I declare a struct with the desired fields with JSON tags to map the values correctly:
type person struct {
Name string `json:"name"`
Age int `json:"age"`
DobDay int `json:"dob_day"`
DobMonth int `json:"dob_month"`
DobYear int `json:"dob_year"`
}
Then I declare an instance of the person struct and use the json package to unmarshal it into the instance of the struct:
var p person
_ = json.Unmarshal(str, &p)
fmt.Println(p)
But when I print out the person, the following output is generated:
{Jim Burnham 0 0 0 0}
As you can see, the string has been parsed correctly but the other integer fields remain at their default Golang initialized value. However, when I change the struct definition to :
type person struct {
Name string `json:"name"`
Age string `json:"age"`
DobDay string `json:"dob_day"`
DobMonth string `json:"dob_month"`
DobYear string `json:"dob_year"`
}
I get the following output:
{Jim Burnham 34 22 3 1984}
This means that currently, I have to define a raw struct which parses the information in the format of a string but then define another struct with the desired dtypes and reassign and convert the values separately, which produces untidy code as well. However, this is just one case but in my use case, there are likely thousands or even sometimes millions of such values and it seems to be inefficient, even for a compiled language. This is why I am asking for solutions for such a problem.
As explained well by #mkopriva at this link: https://play.golang.org/p/klHYlMQyb_V

Empty fields while doing json unmarshal

I have written this piece of code. I can't figure out why it is giving empty fields when i run it. I have tried Uppercase variables. Still doesn't work.
package main
import (
"encoding/json"
"fmt"
)
type FirstName struct {
Name1 string
}
type SecondName struct {
Name2 string
}
type Person struct {
Details FirstName
MoreDetails SecondName
}
func main() {
var someGuy Person
var data = []byte(`{"details": {"firstName": "alan"}, "moreDetails": {"surName": "Turing"}}`)
json.Unmarshal(data, &someGuy)
fmt.Println(someGuy)
}
Your JSON to Go mapping is incorrect. To have automatic matching between struct fields and the JSON properties during the unmarshaling process, the field names (and not the name of their types) must match the properties in JSON (in a case in-sensitive manner):
type FirstName struct {
FirstName string
}
type SecondName struct {
SurName string
}
type Person struct {
Details FirstName
MoreDetails SecondName
}
With this, the output is (try it on the Go Playground):
{{alan} {Turing}}
If you want to keep those names in Go, another option is to provide a mapping between Go struct fields and JSON property names. For this you may use struct tags:
type FirstName struct {
Name1 string `json:"firstName"`
}
type SecondName struct {
Name2 string `json:"surName"`
}
Output will be the same. Try this one on the Go Playground.
For an introduction and more details about struct tags, see What are the use(s) for tags in Go?

Go Nested Json Marshall or Encoding

For a project of mine, i need to encode into Json like below. I have all the values as variables. Any help is appreciated.
{"id":[{"name":"Test","Class":[{"Grade":"2","id":"34"}]}],"age":"5"}
this is the code i have tried
type classx struct {
Grade string `json:"grade"`
Id string `json:"id"`
}
type idx struct {
Name string `json:"name"`
Class []classx
}
type Response struct {
Age string `json:"age"`
Id []idx
}
But getting an error "cannot use classx literal (type classx) as type []classx in field value"
The Class field is a slice. You have given it a struct
Wrong:
Response{Id:[]idx{idx{Class:classx{}}}}
Correct:
Response{Id:[]idx{idx{Class:[]classx{}}}}

Golang and JSON with array of struct [duplicate]

This question already has answers here:
My structures are not marshalling into json [duplicate]
(3 answers)
Closed 7 months ago.
I would like to create a JSON of a GatewayInfo where the type are defined like this:
type SpanInfo struct {
imsi string
network string
network_status string
signal_quality int
slot int
state string
}
type GatewayInfo []SpanInfo
The gateway information is created with:
var gatewayInfo = make(GatewayInfo, nb_spans)
To create the JSON, I use the json.Marshal function:
gatewayInfo := getGatewayInfo(spans)
log.Printf("Polling content: %s\n", gatewayInfo)
jsonInfo, _ := json.Marshal(gatewayInfo)
log.Printf("jsonInfo: %s\n", jsonInfo)
Unfortunately the result is not what I was expecting:
2015/02/09 13:48:26 Polling content: [{652020105829193 20801 Registered (Roaming) %!s(int=17) %!s(int=2) } {652020105829194 20801 Registered (Roaming) %!s(int=16) %!s(int=3) } {652020105829192 20801 Registered (Roaming) %!s(int=19) %!s(int=1) } {652020105829197 20801 Registered (Roaming) %!s(int=19) %!s(int=4) }]
2015/02/09 13:48:26 jsonInfo: [{},{},{},{}]
As we can see, the GatewayInfo instance has the SpanInfo, but in the JSON I have empty SpanInfo.
Your struct fields must be exported (field is exported if it begins with a capital letter) or they won't be encoded:
Struct values encode as JSON objects. Each exported struct field
becomes a member of the object
To get the JSON representation as probably expected change the code to this:
type SpanInfo struct {
IMSI string `json:"imsi"`
Network string `json:"network"`
NetworkStatus string `json:"network_status"`
SignalQuality int `json:"signal_quality"`
Slot int `json:slot"`
State string `json:"state"`
}
type GatewayInfo []SpanInfo
The json package can only serialize exported fields of your struct. Change your struct to start all fields with an uppercase letter so they can be included in the output:
type SpanInfo struct {
Imsi string
Network string
Network_status string
Signal_quality int
Slot int
State string
}
Read the documentation of json.Marshal() for details and more information.
This is not a new answer. It is just consolidation of comments on the
accepted answer.
From ORIGINAL Query
type SpanInfo struct {
imsi string
network string
network_status string
signal_quality int
slot int
state string
}
From Answer and comments - Please note that the first char of each field in struct is now in UPPER case along with json representation added to each field
type SpanInfo struct {
IMSI string `json:"imsi"`
Network string `json:"network"`
NetworkStatus string `json:"network_status"`
SignalQuality int `json:"signal_quality"`
Slot int `json:slot"`
State string `json:"state"`
}

Capitals in struct fields

I'm using this library to access CouchDB (cloudant to be specific) "github.com/mikebell-org/go-couchdb" and I've noticed a problem.
When I go to add a file to the database and pass in a struct, only the fields of the struct which started with a capital letter get added.
For example
type Person struct {
name string
Age int
}
func main() {
db, _ := couchdb.Database(host, database, username, password)
joe := Person{
name: "mike",
Age: 190,
}
m, _ := db.PostDocument(joe)
}
In this case, only the "age" field got updated and inserted into my database.
I've noticed this problem in another case also - when I'm doing something like this :
type Sample struct {
Name string
age int
}
joe := Sample{
Name: "xx",
age: 23,
}
byt, _ := json.Marshal(joe)
post_data := strings.NewReader(string(byt))
fmt.Println(post_data)
in this case, only Name would be printed out :
output : &{{"Name":"xx"} 0 -1}
Why is this? and If I would like to have a field with a lowercase and be inside the database, is that possible?
This is because only fields starting with a capital letter are exported, or in other words visible outside the curent package (and in the json package in this case).
Here is the part of the specifications refering to this: http://golang.org/ref/spec#Exported_identifiers
Still, you can unmarshall json fields that do no start with a capital letters using what is called "tags". With the json package, this is the syntax to use:
type Sample struct {
Name string `json:"name"`
Age int `json:"age"`
}
Refer to the documentation for more information about this.
json package only stringfiy fields start with capital letter.
see http://golang.org/pkg/encoding/json/
Struct values encode as JSON objects. Each exported struct field becomes a member of the object, using the field name as the object key, unless the field is omitted for one of the reasons given below.
You need define the struct like this:
type Sample struct{
Name string `json:"name"`
Age int `json:"age"`
}
json.Marshal method struct-in field-i only accepts fields that start with a capital letter
The json package only accesses the exported fields of struct types (those that begin with an uppercase letter). Therefore only the exported fields of a struct will be present in the JSON output.
type Sample struct {
Name string
Age int
}