Parsing Json In Golang - json

Have been trying to parse this json file using go to get the Minimum and Maximum Temperature
of a given city.
{
"data": {
"current_condition": [
{
"cloudcover": "25",
"humidity": "56",
"observation_time": "01:33 PM",
"precipMM": "0.0",
"pressure": "1016",
"temp_C": "20",
"temp_F": "68",
"visibility": "10",
"weatherCode": "116",
"weatherDesc": [
{
"value": "Partly Cloudy"
}
],
"weatherIconUrl": [
{
"value": "http://cdn.worldweatheronline.net/images/wsymbols01_png_64/wsymbol_0002_sunny_intervals.png"
}
],
"winddir16Point": "SSW",
"winddirDegree": "210",
"windspeedKmph": "7",
"windspeedMiles": "4"
}
],
"request": [
{
"query": "London, United Kingdom",
"type": "City"
}
],
"weather": [
{
"date": "2014-09-07",
"precipMM": "0.0",
"tempMaxC": "23",
"tempMaxF": "74",
"tempMinC": "10",
"tempMinF": "49",
"weatherCode": "119",
"weatherDesc": [
{
"value": "Cloudy"
}
],
"weatherIconUrl": [
{
"value": "http://cdn.worldweatheronline.net/images/wsymbols01_png_64/wsymbol_0003_white_cloud.png"
}
],
"winddir16Point": "N",
"winddirDegree": "355",
"winddirection": "N",
"windspeedKmph": "9",
"windspeedMiles": "6"
}
]
}
}
Have been successful using structures and decoding the json string.
Now i want to try using maps, such as map[string]interface{}
If u is of type map[string]interface{} and the json is parsed into u,
u["data"].(map[string]interface{})["weather"]
gives the value
http://api.worldweatheronline.com/free/v1/weather.ashx?q=london&format=json&num_of_days=1&key=8c52bb73c5f6160f5f3aa535d22184638372d22b [map[tempMaxC:23 tempMaxF:74 tempMinC:10 tempMinF:49 winddirection:N windspeedMiles:6 date:2014-09-07 precipMM:0.0 weatherCode:119 winddir16Point:N winddirDegree:355 weatherDesc:[map[value:Cloudy]] weatherIconUrl:[map[value:http://cdn.worldweatheronline.net/images/wsymbols01_png_64/wsymbol_0003_white_cloud.png]] windspeedKmph:9]]
whereas u["data"].(map[string]interface{})["weather"].(map[string]interface{})["tempMinC"],
gives me an panic: interface conversion: interface is []interface {}, not map[string]interface {}
Can someone explain what's happening?

u["data"].(map[string]interface{})["weather"] is a slice of maps, not a map, so you would have to do something like :
maps, ok := u["data"].(map[string]interface{})["weather"].([]interface{})
if !ok {
panic("bad json")
}
for _, m := range maps {
if m, ok := m.(map[string]interface{}); ok {
fmt.Println(m["tempMinC"])
}
}
From your JSON example, weather is an array of objects so this translates to a slice of maps ([]map[string]interface{})in Go.

It's a slice not a map.
range the u["data"].(map[string]interface{})["weather"]

Related

JSONata transpose a dynamic sized object

I have a json response from a REST API that looks like:
{
"Data": [
{
"Name": "MeasurementID1",
"Samples": [
{
"Time": "2021-12-31T11:15:00.000Z",
"Value": "3.280642033",
},
{
"Time": "2021-12-31T12:15:00.000Z",
"Value": "0.06151203811",
}
]
},
{
"Name": "MeasurementID2",
"Samples": [
{
"Time": "2021-12-31T11:15:00.000Z",
"Value": "53.91226196",
},
{
"Time": "2021-12-31T12:15:00.000Z",
"Value": "56.34856796",
}
]
}
]
}
I would like to transform this data for plotting in Grafana where the data is an array of table rows like
[
{ "Time": "2021-12-31T11:15:00.000Z", "MeasurementID1": "3.280642033", "MeasurementID2": "53.91226196".........."MeasurementIDxx": xxx},
{ "Time": "2021-12-31T12:15:00.000Z", "MeasurementID1": "0.06151203811", "MeasurementID2": "56.34856796".........."MeasurementIDxx": xxx}
]
I've hit a stumbling block in that the number of objects in the "Data" array is dynamic and is based on the # requested in rest api get request.
I'm stuck and don't have enough knowledge to do this transformation
If you flattened the structure a bit first, you can use the 'group-by' construct:
Data.Samples.{
"Name": %.Name,
"Time": Time,
"Value": Value
}{Time: $} ~> $each(function($v) {
$merge($v.{"Time": Time, Name: Value})
})
See https://try.jsonata.org/NXMIg7e0R
I was able to solve it by using 2 nested $reduce calls. Check it out here: https://stedi.link/egfbW8g
$reduce(Data, function($dataAcc, $dataItem) {(
$reduce($dataItem.Samples, function($samplesAcc, $sampleItem) {(
$existingItemForTime := $lookup($samplesAcc, $sampleItem.Time);
$patchForTime := {"Time": $sampleItem.Time, $dataItem.Name: $sampleItem.Value };
$merge([$samplesAcc, { $sampleItem.Time: $merge([$existingItemForTime, $patchForTime]) }])
)}, $dataAcc);
)}, {}) ~> $each(function($v) { $v })

Swift, JSON model

I have a question regarding building a JSON model namely, I should declare a date that will be different each day - in this case: "2020-11-19" as below.
This is a response for the current day.
{
"dates": {
"2020-11-19": {
"countries": {
"Poland": {
"date": "2020-11-19",
"id": "poland",
"links": [
{
"href": "/api/2020-11-19/country/poland",
"rel": "self",
"type": "GET"
}
],
"name": "Poland",
"name_es": "Polonia",
"name_it": "Polonia",
"regions": [],
"source": "John Hopkins University",
"today_confirmed": 796798,
"today_deaths": 12088,
"today_new_confirmed": 23975,
"today_new_deaths": 637,
"today_new_open_cases": 4335,
"today_new_recovered": 19003,
"today_open_cases": 422824,
"today_recovered": 361886,
"today_vs_yesterday_confirmed": 0.03102262743215456,
"today_vs_yesterday_deaths": 0.05562832940354556,
"today_vs_yesterday_open_cases": 0.010358695210626712,
"today_vs_yesterday_recovered": 0.055421236981710864,
"yesterday_confirmed": 772823,
"yesterday_deaths": 11451,
"yesterday_open_cases": 418489,
"yesterday_recovered": 342883
}
},
"info": {
"date": "2020-11-19 00:00CET",
"date_generation": "2020-11-19 22:34",
"yesterday": "2020-11-18 00:00CET"
}
}
},
"metadata": {
"by": "Narrativa & AppliedXL",
"url": [
"wwww.narrativa.com",
"www.appliedxl.com"
]
},
"total": {
"date": "2020-11-19",
"name": "Total",
"name_es": "Total",
"name_it": "Total",
"rid": "#total",
"source": "Narrativa",
"today_confirmed": 56684618,
"today_deaths": 1356365,
"today_new_confirmed": 525111,
"today_new_deaths": 8186,
"today_new_open_cases": 273944,
"today_new_recovered": 242981,
"today_open_cases": 19082735,
"today_recovered": 36245518,
"today_vs_yesterday_confirmed": 0.009350349175964112,
"today_vs_yesterday_deaths": 0.00607189401407382,
"today_vs_yesterday_open_cases": 0.014564678824917632,
"today_vs_yesterday_recovered": 0.00674899660543371,
"yesterday_confirmed": 56159507,
"yesterday_deaths": 1348179,
"yesterday_open_cases": 18808791,
"yesterday_recovered": 36002537
},
"updated_at": "2020-11-19 21:34UTC"
}
How I should build a model so that this property would be changed every day? (of course, this date needs to have a proper format "yyyy-MM-dd")
I would probably do:
var dates: [String: YourModel]
if it will potentially have multiple dates in that field.. otherwise, I'd probably do a custom object that overrides init(from decoder: and parses out that info

Enumerate slice entries

If I have this output
Stuff {
"Items": [
{
"title": "test1",
"id": "1",
},
{
"title": "test",
"id": "2",
},
],
"total": 19
},
}
But want this instead:
stuff {
"Items": [
1:{
"title": "test1",
"id": "1",
},
2:{
"title": "test",
"id": "2",
},
],
"total": 19
},
}
Currently, my structs are build like this:
Stuff struct {
Items []Items `json:"items"`
Total int `json:"total"`
} `json:"stuff"`
type Items struct {
Title string `json:"title"`
ID string `json:"id"`
}
I initiate a slice by:
stuff := make([]Items, 10) // Lets say I have 10 entries
And append by:
Stuff.Items = stuff
Stuff.Total = len(Stuff.Items)
Now I am unsure on how to numerate that. So for every item entries, there should be a number, starting from 1 - 10 (In this example)
Given your Stuff and Items type declarations, here's a simple data structure and its JSON dump:
s := Stuff{Items: []Items{Items{"test1", "1"}, Items{"test2", "2"}}, Total: 10}
j, err := json.MarshalIndent(s, "", " ")
if err != nil {
log.Fatal(err)
}
fmt.Println(string(j))
JSON:
{
"items": [
{
"title": "test1",
"id": "1"
},
{
"title": "test2",
"id": "2"
}
],
"total": 10
}
To see what you want instead, there's no magic json package call to do that. You'll have to create a new data structure that reflects the structure of your desired output.
In this case a simple map will do:
m := make(map[string]Items)
for _, item := range s.Items {
m[item.ID] = item
}
And now if you JSON-dump this map, you get:
{
"1": {
"title": "test1",
"id": "1"
},
"2": {
"title": "test2",
"id": "2"
}
}
Note that I'm not wrapping it with Stuff now, because Stuff has different fields. Go is statically typed, and each struct can only contain the fields you declared it to have.

JSON object extract from big query database using app script

I have a big query table that has a JSON object as one of the field in the table. How can I extract the data from the JSON object using app script. The object itself is nested. It looks like this
{
"uid": "124551",
"subjects": [
{
"tid": 37,
"title": "Algebra",
"html_id": "algebra",
"selected": true
},
{
"tid": 214853,
"title": "Trigonometry",
"html_id": "trigonometry",
"selected": true
},
{
"tid": 38,
"title": "Geometry",
"html_id": "geometry",
"selected": true
}
],
"cellphone": "09178854579",
"educations": [
{
"index": 0,
"schoolname": "University of the Philippines - Los BaƱos",
"degree": "BS Mathematics",
"major": "Mathematics",
"eduFrom": "2009-05-31T16:00:00.000Z",
"eduTo": "2013-04-26T16:00:00.000Z",
"eduFromTs": 1243785600,
"eduToTs": 1366992000
}
],
"info": {
"os": "Windows",
"internet": "ADSL",
"browser": "Chrome",
"network": "Wireless",
"speed": "",
"timezone": "Asia/Hong_Kong"
}
}
I want to extract all school names from education field. Any ideas?
Working with JSON objects is similar to working with XML, except that parsing or encoding a JSON object is much easier.
Once this string is retrieved, simply call JSON.parse() on the string to get a native object representation.
var data = JSON.parse(json);
Browser.msgBox(data.info.os);
Other sample code is at https://developers.google.com/apps-script/advanced/bigquery#run_query

creating JSON object without using a list

I want to be able to create a JSON object so that I can access it like this.
education.schools.UNCC.graduation
Currently, my JSON is like this:
var education = {
"schools": [
"UNCC": {
"graduation": 2015,
"city": "Charlotte, NC",
"major": ["CS", "Spanish"]
},
"UNC-CH": {
"graduation": 2012,
"city": "Chapel Hill, NC"
"major": ["Sociology", "Film"]
}
],
"online": {
"website": "Udacity",
"courses": ["python", "java", "data science"]
}
};
When I go to Lint my JSON, I get an error message.
I know I can reformat my object to access it like this (below), but I don't want to do it this way. I want to be able to call the school name, and not use an index number.
education.schools[1].graduation
Objects have named keys. Arrays are a list of members.
Replace the value of "schools" with an object. Change [] to {}.
This is your JSON corrected.
Your JSON is invalid.
{
"schools": [
{
"UNCC": {
"graduation": "2015",
"city": [
"CS",
"Spanish"
],
"major": [
"CS",
"Spanish"
]
}
},
{
"UNC-CH": {
"graduation": "2012",
"city": [
"Chapel Hill",
"NC"
],
"major": [
"Sociology",
"Film"
]
}
}
],
"online": {
"website": "Udacity",
"courses": [
"python",
"java",
"data science"
]
}
}
Explanation:
"city": "Chapel Hill, NC" -> this is a array with 2 values "Chapel Hill" and "HC", like you do with major and courses.
The Schools array, you need to use this sintaxe to construct a array [{
http://adobe.github.io/Spry/samples/data_region/JSONDataSetSample.html