How to unmarshall JSON in golang - json

I have trouble unmarshal access the values of a JSON string in my golang service.
I read the documentation for golang but the JSON objects in the examples are all differently formated.
from my api i get the following JSON string:
{"NewDepartment":
{
"newDepName":"Testabt",
"newDepCompany":2,
"newDepMail":"Bla#bla.org"
}
}
in go I defined the following data types:
type NewDepartment struct {
NewDepName string `json:"newDepName"`
NewDepCompany int `json:"newDepCompany"`
NewDepMail string `json:"newDepMail"`
}
type NewDeps struct {
NewDeps []NewDepartment `json:"NewDepartment"`
}
I try to unmarshal the JSON (from request Body) and access the values, but I can't get any results
var data types.NewDepartment
errDec := json.Unmarshal(reqBody, &data)
fmt.Println("AddDepartment JSON string got: " + data.NewDepName)
but it contains no string - nothing is displayed but no error on unmarshaling or Println.
Thanks for the help.

You're almost there.
First update is to make NewDeps.NewDeps a single object, not an array (according to the provided JSON).
The second update is to deserialize JSON into NewDeps, not into NewDepartment.
Working code:
type NewDepartment struct {
NewDepName string `json:"newDepName"`
NewDepCompany int `json:"newDepCompany"`
NewDepMail string `json:"newDepMail"`
}
type NewDeps struct {
NewDeps NewDepartment `json:"NewDepartment"`
}
func main() {
var data NewDeps
json.Unmarshal([]byte(body), &data)
fmt.Println("AddDepartment JSON string got: " + data.NewDeps.NewDepName)
}
https://play.golang.org/p/Sn02hwETRv1

Related

How to set optional json in nest struct

I tried to set an optional json config in nest struct, when i need this json it will appear, otherwise it will not exist.
type Test struct {
Data NestTest `json:"data"`
}
type NestTest struct {
NestData1 string `json:"data1"`
NestData2 string `json:"data2,omitempty"`
}
test := Test{
Data: NestTest{
NestData1: "something",
},
}
b, err := json.Marshal(test)
fmt.Sprintf("the test struct json string is: %s", string(b))
output:
{"data":{"data1":"something","data2":""}}
expect:
{"data":{"data1":"something"}}
All fields are optional when unmarshalling (you won't get an error if a struct field doesn't have an associated value in the JSON). When marshaling, you can use omitempty to not output a field if it contains its type's zero value:
https://pkg.go.dev/encoding/json#Marshal
var Test struct {
Data string `json:"data,omitempty" validate:"option"`
}

JSON decode specific field golang

I have this simple function, which gets a JSON response from a specific URI. The function accepts the httpRequest and an interface{}, which is a pointer to the struct in which I want to unmarshal my JSON response.
func (c *Client) SendRequest(req *http.Request, v interface{}) error {
...
return json.NewDecoder(resp.Body).Decode(&v)
}
An example of JSON response is:
{
"data": {
"id": "9da7a204-544e-5fd1-9a12-61176c5d4cd8"
}
}
An example of struct is:
type User struct {
ID string `json:"id;omitempty"`
}
Now, the problem is the data object. With this object, the Decode operation fails, as the object it is not included in my struct. I would like to Decode the content of data object directly, without using a temporary struct, but I don't understand how to do it.
Use a struct that contains a User struct to unmarshal into. See Response struct below.
type User struct {
ID string `json:"id;omitempty"`
}
type Response struct {
Data User `json:"data"`
}
After unmarshaling if r is your Response instance you can access your User by r.Data
Since you don't know the type at compile time you can use interface{} as the type of the field too.
type Response struct {
Data interface{} `json:"data"`
}
r := Response{
Data: &User{},
}
json.NewDecoder(resp.Body).Decode(&r)
And then get your user instance by
userNew, _ := r.Data.(*User)
P.S: You have a typo on your code at json tag. Replace ; by ,

How can I create a nested json structure including a []byte type?

I'm currently trying to create the following nested json including a list of json and DER encoded byte array () of a certificate using golang:
{
"webhooks":
[{
"clientConfig":{
"caBundle":"<derData []bytes>"
},
"name":"sth_name"
}]
}
Because of <certDerBytes[]>, I need to use a struct, but I don't know how to initialize it.
I've created the struct so far:
type jsonstruct struct {
Webhooks []struct {
ClientConfig struct {
CaBundle string `json:"caBundle"`
} `json:"clientConfig"`
Name string `json:"name"`
} `json:"webhooks"`
}
But cannot instantiate the struct which I have to marshal into json.
I've tried using string literals, many ways of initializing it as you would for a normal non-nested struct.
I've also dividing up the structs i.e. type jsonstruct.. type webhooks ..., etc, but that errored.
I've also initialized the struct from the inside out, but didn't work either.
I need to create the
You're best off probably using base64 on the byte array itself, and include that as the payload of the struct field.
One piece of nit, I personally do not like nested named-structs. Breaking them out lets you have much more flexibility in your code.
For example:
type jsonstruct struct {
Webhooks []Webhook `json:"webhooks"`
}
type Webhook struct {
ClientConfig ClientConfig `json:"clientConfig"`
Name string `json:"name"`
}
type ClientConfig struct {
CaBundle string `json:"caBundle"`
}
func (cc ClientConfig) ToBytes() []byte {
return []byte(base64.StdEncoding.DecodeString(cc.CaBundle))
}
func (cc ClientConfig) FromBytes(cert []byte) {
cc.CaBundle = base64.StdEncoding.EncodeToString(cert)
}

JSON unmarshal in nested struct

I am trying to unmarshal an incoming JSON into a struct that contains an array of structs. However I get the error
"Invalid input. JSON badly formatted. json: cannot unmarshal array into Go struct field DataInput.Asset of type app.AssetStorage"
I have tried to recreate the code here: https://play.golang.org/p/RuBaBjPmWxO, however I can't reproduce the error (although the incoming message and code are identical).
type AssetStorage struct {
Event string `json:"Event"`
EmployeeID int `json:"EmployeeID"`
EmployeeEmail string `json:"EmployeeEmail"`
PerformedBy string `json:"PerformedBy"`
Timestamp string `json:"Timestamp"`
AlgorithmID string `json:"AlgorithmID"`
AlgorithmHash string `json:"AlgorithmHash"`
Objects []Object `json:"Objects"`
}
type Object struct {
ShortName string `json:"ShortName"`
Hash string `json:"Hash"`
DestroyDate string `json:"DestroyDate"`
}
type DataInput struct {
Username string
Token string `json:"Token"`
Asset AssetStorage `json:"Asset"`
}
func main() {
var data DataInput
json.Unmarshal(input, data)
data.Username = data.Asset.EmployeeEmail
fmt.Printf("%+v\n", data)
}
There are three bugs in your code, one is that your are not using address of DataInput struct when you are unmarshalling your JSON.
This should be:
var data DataInput
json.Unmarshal(input, data)
like below:
var data DataInput
if err := json.Unmarshal(input, &data); err != nil {
log.Println(err)
}
One Piece of advice in above code. Never skip errors to know more about the error
Next as the error says:
Invalid input. JSON badly formatted. json: cannot unmarshal array into
Go struct field DataInput.Asset of type app.AssetStorage
DataInput.Asset should be an array of json objects there you should change your AssetStorage to []AssetStorage in your declaration in DataInput struct.
One more error is that you are declaring the type of EmployeeID field for AssetStorage struct to be an int which should be a string
Working Code on Go Playground
The answer is in the error message:
Invalid input. JSON badly formatted. json: cannot unmarshal array into Go struct field DataInput.Asset of type app.AssetStorage
The json you're parsing has DataInput.Asset as an array of AssetStorage objects. So, the type needs to be []AssetStorage.

How to convert JSON string to struct

I have start working in golang, I am trying to parse JSON string to struct but its not working.
JSON String:
dailies":[{"userAccessToken":"acessToken","uploadStartTimeInSeconds":1499744832,"uploadEndTimeInSeconds":1499744832,"callbackURL":"callbackurl"}]}
type pingDataFormat struct {
userAccessToken string
uploadStartTimeInSeconds int
uploadEndTimeInSeconds int
callbackURL string
}
Below is code which convert JSON String to structs
pingJSON := make(map[string][]pingDataFormat)
err := json.Unmarshal([]byte(pingData), &pingJSON)
if err != nil {
panic(err)
}
fmt.Printf("\n\n json object:::: %v", pingJSON)
output is:
json object:::: map[dailies:[{ 0 0 }]]
Here "dailies" dont have data, So do i following right approach to parse and how to get data after parse?
The fields in pingDataFormat need to be exported (start with a capital letter)
type pingDataFormat struct {
UserAccessToken string `json:"userAccessToken"`
UploadStartTimeInSeconds int `json:"uploadStartTimeInSeconds"`
UploadEndTimeInSeconds int `json:"uploadEndTimeInSeconds"`
CallbackURL string `json:"callbackURL"`
}
That should solve your problem
https://play.golang.org/p/Z3yszFl01L