json object with nested structures in golang - json

I have the following json object that I am trying to represent with Go as a type JsonObject struct
and pass it back in its original json so that I can return the json as an api endpoint. Any advice/example?
[{
"time": 173000,
"id": "VLSuEE5m1kmIhgE7ZhHDFe",
"height": "",
"DATASTRUCTURE": {
},
"language": "en",
"size": 0,
"url": "http://www.gstatic.com/play.m3u8",
"type": "vid",
"definitionid": "h264",
"reference": "PAN-EN",
"content": "This is some content",
"revisiondate": "2017-11-29T00:00:00",
"data": {
},
"id": "BBBB3424-153E-49DE-4786-013B6611BBBB",
"thumbs": {
"32": "https://www.gstatic.com/images?q=tbn:ANd9GcRj",
"64": "https://www.gstatic.com/images?q=tbn:DPd3GcRj"
},
"title": "Cafeteria",
"hash": "BBBB5d39bea20edf76c94133be61BBBB"
}]

You can use https://mholt.github.io/json-to-go/ to generate struct for the given json schema.
For example, json given in the question can be represented like:
type AutoGenerated []struct {
Time int `json:"time"`
ID string `json:"id"`
Height string `json:"height"`
DATASTRUCTURE struct {
} `json:"DATASTRUCTURE"`
Language string `json:"language"`
Size int `json:"size"`
URL string `json:"url"`
Type string `json:"type"`
Definitionid string `json:"definitionid"`
Reference string `json:"reference"`
Content string `json:"content"`
Revisiondate string `json:"revisiondate"`
Data struct {
} `json:"data"`
Thumbs struct {
Num32 string `json:"32"`
Num64 string `json:"64"`
} `json:"thumbs"`
Title string `json:"title"`
Hash string `json:"hash"`}
Hope this helps!

Related

Unwinding nested data responses into structs when a slice is part of the response

I'd like to get some input into how you would all go about unwinding nested response data into custom structs. Below is an example of the data i'm being returned. I'm trying to get to the user data.
{
"_links": {
"self": {
"href": "/api/v2/user-search/default/test?after=1585612800000&limit=20&offset=0&q=johnsmith%40test.com",
"type": "application/json"
}
},
"totalCount": 1,
"items": [
{
"lastPing": "2020-04-30T02:56:10.430867577Z",
"environmentId": "xxxx",
"ownerId": "xxxx",
"user": {
"key": "johnsmith#test.com",
"email": "johnsmith#test.com",
"firstName": "john",
"lastName": "smith"
},
"_links": {
"parent": {
"href": "/api/v2/users/default/test",
"type": "application/json"
},
"self": {
"href": "/api/v2/users/default/test/johnsmith#test.com",
"type": "application/json"
},
"settings": {
"href": "/api/v2/users/default/test/johnsmith#test.com/flags",
"type": "text/html"
},
"site": {
"href": "/default/test/users/johnsmith#test.com",
"type": "text/html"
}
}
}
]
}
Currently I'm doing the below
respData := map[string][]map[string]map[string]interface{}{}
json.Unmarshal(respBody, &respData)
userData := respData["items"][0]["user"]
I'd love to be able to unmarshal it into a custom struct but I can't seem to get it to work. The nested slice that the user object sits within is what keeps throwing me off.
type User struct {
Key string `json:"key"`
Email string `json:"email"`
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
}
type LinkInfo struct {
Href string `json:"href"`
Type string `json:"type"`
}
type Item struct {
LastPing time.Time `json:"lastPing"`
EnvironmentID string `json:"environmentId"`
OwnerID string `json:"ownerId"`
User User `json:"user"`
Links LinkInfo `json:"_links"`
Self LinkInfo `json:"self"`
Settings LinkInfo `json:"settings"`
Parent LinkInfo `json:"parent"`
Site LinkInfo `json:"site"`
}
type ItemDetails struct {
Links LinkInfo `json:"_links"`
TotalCount int `json:"total_count"`
Items []Item
}
Can you try this?
https://play.golang.org/p/S_CUN0XEh-d
From what you mentioned it sounds like you were on the right track. Your JSON is pretty large, so let me give you a smaller example similar to the part you mentioned you're having trouble with (the user object inside the items list).
type response struct {
TotalCount int `json:"totalCount"`
Items []*itemStruct `json:"items"`
}
type itemStruct struct {
LastPing string `json:"lastPing"`
User *userStruct `json:"user"`
}
type userStruct struct {
Key string `json:"key"`
}
Basically to map to a JSON list of objects, just put a field like this in your struct: Objects []*structWhichMapsToMyObject
Edit: Here's the code running in Go Playground: https://play.golang.org/p/EvSvv-2s8y8
If you want this:
"user": {
"key": "johnsmith#test.com",
"email": "johnsmith#test.com",
"firstName": "john",
"lastName": "smith"
}
Declare a matching Go struct:
type User struct {
Key string `json:"key"`
Email string `json:"email"`
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
}
Then, since the user's parent object looks like this:
"items": [
{
"lastPing": "2020-04-30T02:56:10.430867577Z",
"environmentId": "xxxx",
"ownerId": "xxxx",
"user": { ... },
"_links": { ... }
}
]
you also need to declare a matching Go struct for that (you can omit fields you don't need):
type Item struct {
User User `json:"user"`
}
and then the parent of the parent:
{
"_links": {
"self": {
"href": "/api/v2/user-search/default/test?after=1585612800000&limit=20&offset=0&q=johnsmith%40test.com",
"type": "application/json"
}
},
"totalCount": 1,
"items": [ ... ]
}
and the matching Go struct for the grandparent, again, include only the fields you need:
type ResponseData struct {
Items []Item `json:"items"`
}
Once you have this you can decode the json into an instance of ResponseData:
var rd ResponseData
if err := json.Unmarshal(data, &rd); err != nil {
panic(err)
}
for _, item := range rd.Items {
fmt.Println(item.User)
}
https://play.golang.com/p/7yavVSBcHQP

Convert string having json to json or struct

I am getting this type of response from an API:
{
"ok": true,
"response": "[
{
"Id": 163,
"Name": "Availability",
"Path": "Performance|Tier1",
"frequency": "ONE_MIN",
"Values": [
{
"startTimeInMillis": 1571314200000,
"occurrences": 1,
"current": 1,
"min": 0,
"max": 0,
"useRange": false,
"count": 1,
"sum": 1,
"value": 1,
"standardDeviation": 0
},
{
"startTimeInMillis": 1571314260000,
"occurrences": 1,
"current": 1,
"min": 0,
"max": 0,
"useRange": false,
"count": 1,
"sum": 1,
"value": 1,
"standardDeviation": 0
},
}
]
}
]
}
I want to convert this into time series format. To do so first I am trying to unmarshal the response to this struct:
type App struct{
ID string `json:"metric_id"`
Name string `json:"metric_name"`
Path string `json:"metric_path"`
Frequency string `json:"frequency"`
Values []string `json:"metric_values"`
}
I am doing this:
apprsp := App{}
fmt.Println(json.Unmarshal([]byte(ame.Response), &apprsp))
But I am getting error while json.Unmarshal.
What I am trying to do is to generate a json of format:
{'time':'value','time1':'value2'}
Where time/time1 and value/value2 is startTimeInMillis and value from values array.
What I am doing wrong while json unmarshal? What should be done to unmarshal the above data?
Your App structure is not even closely related to the json document you're trying to unmarshal. To unmarshal a json document, you have to have a Go structure that somewhat matches the structure of the underlying document.
type ResponseValue struct {
StartTime int64 `json:"startTimeMillis"`
// other elements of Values here, if you're interested in them
}
type Response struct {
Id int `json:"Id"`
Name string `json:"Name"`
Path string `json:"Path"`
Frequency string `json:"frequency"`
Values []ResponseValue `json:"Values"`
}
type Body struct {
Response []Response `json:"response"`
}
var data Body
json.Unmarshal([]byte(ame.Response),&data)
Then, you can extract the time series from data.
As the one above me just said your mapping from your json to the struct is wrong.
An easy way to find the write mapping is to use this tool https://mholt.github.io/json-to-go/
It enables you to map json to an auto generated struct.
here is your response struct
type Response struct {
ID int `json:"Id"`
Name string `json:"Name"`
Path string `json:"Path"`
Frequency string `json:"frequency"`
Values []struct {
StartTimeInMillis int64 `json:"startTimeInMillis"`
Occurrences int `json:"occurrences"`
Current int `json:"current"`
Min int `json:"min"`
Max int `json:"max"`
UseRange bool `json:"useRange"`
Count int `json:"count"`
Sum int `json:"sum"`
Value int `json:"value"`
StandardDeviation int `json:"standardDeviation"`
} `json:"Values"`
}

Validation for Nested JSON object

{
"firstname": "sathish",
"lastname": "kumar",
"city": {
"id": 12,
"name": "coimbatore"
},
"referrals": [
{
"name": "vignesh",
"mobile": "1234567890"
},
{
"name": "melvin",
"mobile": "1234567890"
}
]
}
Above is my JSON request for creating new profile. I need to do validation for above JSON using Beego validation package
type ProfileForm struct {
Firstname string `json:"firstname" valid:"Required"`
Lastname string `json:"lastname" valid:"Required"`
City struct {
ID int `json:"id" valid:"Required"`
Name string `json:"name" valid:"Required"`
} `json:"city"`
Referrals []struct {
Name string `json:"name" valid:"Required"`
Mobile string `json:"mobile" valid:"Required"`
} `json:"referrals"`
}
I need to know the how can write the validation for JSON request using struct in Beego. Let me know are the any package or tutorial for this kind of requirement.
In official beego documentation I didn't see anything matches my requirement.

JSON string array without Keys into a GoLang struct

I am trying to parse JSON that is submitted from a POST request into a struct in a web service to send email. The following JSON is submitted in the body of the request.
{
"body": {
"template": "abctemplate.html",
"params": {
"name": "Chase",
"email": "1234#gmail.com"
}
},
"to": [
"abc#gmail.com",
"xyz#gmail.com"
],
"cc": [
"xxx#example.com",
"yyy#example.com"
],
"replyTo": {
"email": "aaa#gmail.com",
"name": "Jack"
},
"bcc": "ccc#gmail.com",
"subject": "Hello, world!"
}
This is mapped and read into the following struct
type emailData struct {
Body struct {
Template string `json:"template"`
Params map[string]string `json:"params"`
} `json:"body"`
To map[string]string `json:"To"` // TODO This is wrong
CC string `json:"cc"` // TODO this is wrong
ReplyTo struct {
Email string `json:"email"`
Name string `json:"name"`
}
BCC string `json:"bcc"`
Subject string `json:"subject"`
}
Both the 'to' and 'cc' JSON fields are string arrays of unknown length and do not have keys. Is there a way to map the string arrays into the struct fields? I've tried the two different ways where there are // TODO tags with no luck. Thanks!
Both cc and to are json arrays which you can unmarshal into Go slices without worrying about the length.
type emailData struct {
Body struct {
Template string `json:"template"`
Params map[string]string `json:"params"`
} `json:"body"`
To []string `json:"to"`
CC []string `json:"cc"`
ReplyTo struct {
Email string `json:"email"`
Name string `json:"name"`
}
BCC string `json:"bcc"`
Subject string `json:"subject"`
}
https://play.golang.org/p/Pi_5aSs922
Use the below to convert the json to struct in golang:
Json-goStruct
Take care of the maps, which might be go struct and vice-versa.

Unable to decode the JSON response

I have the following response from a graph api
{
"data": [
{
"name": "Mohamed Galib",
"id": "502008940"
},
{
"name": "Mebin Joseph",
"id": "503453614"
},
{
"name": "Rohith Raveendranath",
"id": "507482441"
}
],
"paging": {
"next": "https://some_url"
}
}
I have a struct as follows
type Item struct {
Name, Id string
}
I wanted to parse the response and get an array of Item, How do I do that?
You need to update your struct like so:
type Item struct {
Name string `json:"name"`
Id string `json:"id"`
}
and add a struct to represent the wrapper:
type Data struct {
Data []Item `json:"data"`
}
You can then use json.Unmarshal to populate a Data instance.
See the example in the docs.