How to parse partial objects inside Json - json

I have the Json structure below, and i'm trying to parse only the key field inside the object. It's possible to do it without mapping the complete structure?
{
"Records":[
{
"eventVersion":"2.0",
"s3":{
"s3SchemaVersion":"1.0",
"configurationId":"my-event",
"bucket":{
"name":"super-files",
"ownerIdentity":{
"principalId":"41123123"
},
"arn":"arn:aws:s3:::myqueue"
},
"object":{
"key":"/events/mykey",
"size":502,
"eTag":"091820398091823",
"sequencer":"1123123"
}
}
}
]
}
// Want to return only the Key value
type Object struct {
Key string `json:"key"`
}

There are a few 3rd party json libraries which are very fast at extracting only some values from your json string.
Libraries:
http://jsoniter.com/
https://github.com/tidwall/gjson
https://github.com/buger/jsonparser
GJSON example:
const json = `your json string`
func main() {
keys := gjson.Get(json, "Records.#.s3.object.key")
// would return a slice of all records' keys
singleKey := gjson.Get(json, "Records.1.s3.object.key")
// would only return the key from the first record
}

Object is part of S3, so I created struct as below and I was able to read key
type Root struct {
Records []Record `json:"Records"`
}
type Record struct {
S3 SS3 `json:"s3"`
}
type SS3 struct {
Obj Object `json:"object"`
}
type Object struct {
Key string `json:"key"`
}

Related

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)
}

How to unmarshall JSON in golang

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

Unmarshall JSON with a [int]string map contained in an array

Im trying to unmarshall the following JSON into a struct, but there I am unable to translate the contents of the values field with the [[int,string]]
This is what I have so far:
type Response struct {
Metric struct {
Name string `json:"name,omitempty"`
Appname string `json:"appname,omitempty"`
} `json:"metric,omitempty"`
Values []map[int]string `json:"values,omitempty"`
}
The JSON file:
{
"metric":{
"name":"x444",
"appname":"cc-14-471s6"
},
"values":[
[
1508315264,
"0.0012116165566900816"
],
[
1508315274,
"0.0011871631158857396"
]
]
}
The data you showed should be unmarshaled to:
type Response struct {
Metric struct {
Name string `json:"name,omitempty"`
Appname string `json:"appname,omitempty"`
} `json:"metric,omitempty"`
Values [][]interface{} `json:"values,omitempty"`
}
If you want to to transfer it to map implement json.Unmarshaller interface - https://golang.org/pkg/encoding/json/#Unmarshaler
You can have something like:
type Item struct {
Key int
Val string
}
func(item *Item) UnmarshalJSON([]byte) error {
// TODO: implement
}
type Response struct {
Metric struct {
Name string `json:"name,omitempty"`
Appname string `json:"appname,omitempty"`
} `json:"metric,omitempty"`
Values []Item `json:"values,omitempty"`
}

Go - JSON Decoder not initializing my struct

I am trying to decode some JSON retrieved via http.Get. However, when I check the structs I initialize with fmt.Println, they are always empty.
I suspect it is because my struct's structure does not agree with the returned JSON, but I am not sure how to fix it. In general, I am not exactly quite sure how the decoder works.
This is the JSON:
{
"response":[
{
"list": {
"category":"(noun)",
"synonyms":"histrion|player|thespian|role player|performer|performing artist"
}
},
{
"list": {
"category":"(noun)",
"synonyms":"doer|worker|person|individual|someone|somebody|mortal|soul"
}
}
]
}
Here is what i have tried so far:
type SynonymResponse struct {
lists []SynonymList
}
type SynonymList struct {
category string
synonyms string
}
var synonyms SynonymResponse;
dec := json.NewDecoder(response.Body)
err := dec.Decode(&synonyms)
if err != nil {
log.Fatal(err)
}
fmt.Println(synonyms)
EDIT: Per #Leo's answer and #JimB's hint, there are two issues with my attempt. Below is the proper set of structs, though as Leo pointed out, this will be empty:
type SynonymResponses struct {
resp []SynonymResponse
}
type SynonymResponse struct {
listo SynonymList
}
type SynonymList struct {
cat string
syns string
}
In order for your JSON to be picked up by the decoder, the fields in your struct must be exported.
This means you need you capitalize the field names. If you have custom naming on your fields -> json conversion, you can add json tags to your structs.
This will fix your issue:
type SynonymResponse struct {
Lists []SynonymList `json:"response"`
}
type SynonymList struct {
Category string `json:"category"`
Synonyms string `json:"synonyms"`
}