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

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"`
}

Related

Parse a Json file with golang, encountering a problem "cannot unmarshal object into Go value of type"

I have a JSON file as follows:
{
"contracts": [
{
"name": "contract1",
"funcs": [
{
"name": "func1",
"callchain": ["parfunc1", "parfunc2", "parfuncN"],
"stateFuncs": ["stafunc1", "stafunc2", "stafuncN"],
"consOnInputs": ["param1>20", "param2<10", "param4+param5>80"]
},
{
"name": "func2",
"callchain": ["2parfunc1", "2parfunc2", "2parfunN"],
"stateFuncs": ["2stafunc1", "2stafunc2", "2stafuncN"],
"consOnInputs": ["param1>20", "param2<10", "param4+param5>80"]
]
},
{
"name": "contract2",
"funcs": [
{
"name": "func3",
"callchain": ["parfunc5", "parfunc5", "parfuncN"],
"stateFuncs": ["stafunc8", "stafunc8", "stafuncN"],
"consOnInputs": ["param1>20", "param2<10", "param4+param5>80"]
}
]
}
]
}
I encounter the problem json: cannot unmarshal object into Go struct field ContractAll.contracts of type main.ContractInfo
contracts: {[[] []]} with the following unmarshalled codes, where the json_content contains contents of the JSON file:
type FuncInfo struct {
Name string `json:"name"`
Callchain []string `json:"callchain"`
StateFuncs []string `json:"stateFuncs"`
ConsOnInputs []string `json:"consOnInputs"`
}
type ContractInfo []struct{
Name string `json:"name"`
Funcs []FuncInfo `json:"funcs"`
}
type ContractAll struct {
Contracts []ContractInfo `json:"contracts"`
}
var contracts ContractAll
err = json.Unmarshal([]byte(json_content), &contracts)
How can I fix this problem?
Your structures don't match the input. You need one more:
type Contracts struct {
Contracts []ContractInfo `json:"contracts"`
}
...
var contracts Contracts
err = json.Unmarshal([]byte(json_content), &contracts)

GoLang JSON payload preparation with multiple data

I want to create JSON payload in given below format. I want a code or pattern that prepares the given format.
{
transactiontype: 'DDDDD'
emailType: 'QQQQQQ'
template: {
templateUrl: 'xry.kk'
templateName: 'chanda'
}
date: [
{
UserId: 1
Name: chadnan
},
{
UserId: 2
Name: kkkkkk
}
]
}
Hope this helps :
type Template struct {
TemplateURL string `json:"templateUrl" param:"templateUrl"`
TemplateName string `json:"templateName" param:"templateName"`
}
type Date struct {
UserId string `json:"UserId" param:"UserId"`
Name string `json:"Name" param:"Name"`
}
type NameAny struct {
*Template
TransactionType string `json:"transactiontype" param:"transactiontype"`
EmailType string `json:"emailType" param:"emailType"`
Data []Date `json:"date" param:"date"`
}
Data, _ := json.Marshal(NameAny)
Json(c, string(Data))(w, r)
You can use an online tool to convert a json into a valid Go struct: https://mholt.github.io/json-to-go/
Given your JSON, the Go struct is:
type AutoGenerated struct {
Transactiontype string `json:"transactiontype"`
EmailType string `json:"emailType"`
Template struct {
TemplateURL string `json:"templateUrl"`
TemplateName string `json:"templateName"`
} `json:"template"`
Date []struct {
UserID int `json:"UserId"`
Name string `json:"Name"`
} `json:"date"`
}
After the conversion, use the json.Marshal (Go Struct to JSON) and json.Unmarshal (JSON to Go Struct)
Complete example with your data: https://play.golang.org/p/RJuGK4cY1u-
// Transaction is a struct which stores the transaction details
type Transaction struct {
TransactionType string `json:"transaction_type"`
EmailType string `json:"email_type"`
Template Template `json:"template"`
Date []Date `json:"date"`
}
//Template is a struct which stores the template details
type Template struct {
TemplateURL string `json:"template_url"`
TemplateName string `json:"template_name"`
}
// Date is a struct which stores the user details
type Date struct {
UserID int `json:"user_id"`
Name string `json:"name"`
}
Above given structs are the correct data structure for storing your json body you can use json decoder for perfectly storing the data into struct
func exampleHandler(w http.ResponseWriter, r *http.Request) {
var trans Transaction
decoder := json.NewDecoder(r.Body)
err := decoder.Decode(&trans)
if err != nil {
log.Println(err)
}
}

How to parse partial objects inside 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"`
}

Json unmarshal type model in golang

I have a RESTful service that returns response similar to show below:
"Basket" : {
"Count": 1,
"Fruits": {[
{
"Name":"Mango",
"Season":"Summer"
},
{
"Name":"Fig",
"Season":"Winter"}
]}
}
I am trying to create Go lang model to unmarshal the contents. Following is the code I have tried:
type Response struct {
Count int
Fruits []Fruit
}
type Fruit struct {
Name string
Season string
}
But when I marshal the Response object in my test code I don't see similar json. (https://play.golang.org/p/EGKqfbwFvW)
Marshalled data always appears as :
{
"Count":100,
"Fruits":[
{"Name":"Mango","Season":"Summer"},
{"Name":"Fig","Season":"Winter"}
]
}
Notice the Fruits appearing as array [] and not {[]} in original json. How can I model structs in golang for this response?
Your model is totally correct and valid, but the JSON object is not. "Fruits" doesn't have name if it should be key value pair or it should be wrapped in [] not {}.
JSON obj should be formatted like this:
{
"Basket" : {
"Count": 1,
"Fruits": [
{
"Name":"Mango",
"Season":"Summer"
},
{
"Name":"Fig",
"Season":"Winter"
}
]
}
}
And actually invalid json shouldn't work https://play.golang.org/p/yoW7t4NfI7
I would make 'Baskets' a struct within 'Response', create a 'BasketsData' struct, and give it all some labels.
type Fruit struct {
Name string `json:"Name"`
Season string `json:"Season"`
}
type BasketData struct {
Count int `json:"Count"`
Fruits []Fruit `json:"Fruits"`
}
type Response struct {
Basket BasketData `json:"Basket"`
}
This way you will get a top level JSON response when you marshall it.
fruitmania := []Fruit{{Name: "Mango", Season: "Summer"},
{Name: "Fig", Season: "Winter"}}
basket := Response{BasketData{Count: 100, Fruits: fruitmania}}
b, _ := json.Marshal(basket)
fmt.Println(string(b))
checkit-checkit out:
https://play.golang.org/p/TuUwBLs_Ql

Golang : best way to unmarshal following json with string as keys

I have json like
{
"api_type" : "abc",
"api_name" : "xyz",
"cities" : {
"new_york" : {
"lat":"40.730610",
"long":"-73.935242"
},
"london" : {
"lat":"51.508530",
"long":"-0.076132"
},
"amsterdam" : {
"lat":"52.379189",
"long":"4.899431"
}
//cities can be multiple
}
}
I can use following struct to unmarshal
type MyJsonName struct {
APIName string `json:"api_name"`
APIType string `json:"api_type"`
Locations struct {
Amsterdam struct {
Lat string `json:"lat"`
Long string `json:"long"`
} `json:"amsterdam"`
London struct {
Lat string `json:"lat"`
Long string `json:"long"`
} `json:"london"`
NewYork struct {
Lat string `json:"lat"`
Long string `json:"long"`
} `json:"new_york"`
} `json:"locations"`
}
but my city names and numbers will be different in each response, what is a best way unmarshal this type of json where keys can be string which varies.
I would make the locations a map (although you have it called cities in the JSON):
type MyJsonName struct {
APIName string `json:"api_name"`
APIType string `json:"api_type"`
Locations map[string]struct {
Lat string
Long string
} `json:"locations"`
}