Only last row is printing - arrays

this is my go function
func logInFirst(res http.ResponseWriter, req *http.Request) {
type Resp struct {
Result []map[string]interface{} `json:"Result,omitempty"`
Result1 []map[string]interface{} `json:"Result1,omitempty"`
Result2 []map[string]interface{} `json:"Result2,omitempty"`
Status string `json:"Status"`
}
type AxleUser struct {
ShopID string `json:"ShopID"`
VehicleType string `json:"VehicleType"`
}
var Response Resp
Response.Status = "failed"
Result := make(map[string]interface{})
Result1 := make(map[string]interface{})
Result2 := make(map[string]interface{})
//db, err := sql.Open("mysql", "root:chikkIbuddI57#tcp(127.0.0.1:3306)/b2b")
db, err := sql.Open("mysql", "awsgobumpr:gobumpr123#tcp(briaxpgbmpr.cx4twoxoumct.ap-southeast-1.rds.amazonaws.com)/b2b_optimization")
if err != nil {
panic(err.Error())
}
defer db.Close()
rnd := render.New()
b, err := ioutil.ReadAll(req.Body)
defer req.Body.Close()
if err != nil {
panic(err.Error())
}
// Unmarshal the request body
var msg AxleUser
err = json.Unmarshal(b, &msg)
if err != nil {
panic(err.Error())
}
//fmt.Println(msg)
// get shop id from emp table using mobile number and password
brandrows, branderr := db.Query("SELECT DISTINCT brand,model FROM admin_vehicle_table_new WHERE type=?", msg.VehicleType)
if branderr != nil {
panic(branderr.Error())
}
brandcolumns, branderr := brandrows.Columns()
if branderr != nil {
panic(branderr.Error())
}
brandcount := len(brandcolumns)
brandValues := make([]string, brandcount)
brandScanArgs := make([]interface{}, brandcount)
for i := range brandValues {
brandScanArgs[i] = &brandValues[i]
}
for brandrows.Next() {
branderr := brandrows.Scan(brandScanArgs...)
//fmt.Println(branderr)
if branderr != nil {
panic(branderr.Error())
}
for i, v := range brandValues {
Result[brandcolumns[i]] = v
}
Response.Result = append(Response.Result, Result)
}
servicerows, serviceerr := db.Query("SELECT DISTINCT b2b_service_type FROM b2b_service_type WHERE b2b_vehicle_type=? and b2b_flag=0 and b2b_shop_id=0 UNION SELECT b2b_service_type FROM b2b_service_type WHERE b2b_vehicle_type=? and b2b_flag=0 and b2b_shop_id=?", msg.VehicleType, msg.VehicleType, msg.ShopID)
if serviceerr != nil {
panic(serviceerr.Error())
}
servicecolumns, serviceerr := servicerows.Columns()
if serviceerr != nil {
panic(serviceerr.Error())
}
servicecount := len(servicecolumns)
serviceValues := make([]string, servicecount)
serviceScanArgs := make([]interface{}, servicecount)
for i := range serviceValues {
serviceScanArgs[i] = &serviceValues[i]
}
for servicerows.Next() {
serviceerr := servicerows.Scan(serviceScanArgs...)
if serviceerr != nil {
panic(serviceerr.Error())
}
for i, v := range serviceValues {
Result1[servicecolumns[i]] = v
}
Response.Result1 = append(Response.Result1, Result1)
}
repairrows, repairerr := db.Query("SELECT DISTINCT b2b_repair_decription FROM b2b_repair_decription WHERE b2b_vehicle_type=? and b2b_shop_id=0 UNION SELECT b2b_repair_decription FROM b2b_repair_decription WHERE b2b_vehicle_type=? and b2b_shop_id=?", msg.VehicleType, msg.VehicleType, msg.ShopID)
if repairerr != nil {
panic(repairerr.Error())
}
repaircolumns, repairerr := repairrows.Columns()
if repairerr != nil {
panic(repairerr.Error())
}
repaircount := len(repaircolumns)
repairValues := make([]string, repaircount)
repairScanArgs := make([]interface{}, repaircount)
for i := range repairValues {
repairScanArgs[i] = &repairValues[i]
}
for repairrows.Next() {
repairerr := repairrows.Scan(repairScanArgs...)
if repairerr != nil {
panic(repairerr.Error())
}
for i, v := range repairValues {
Result2[repaircolumns[i]] = v
}
Response.Result2 = append(Response.Result2, Result2)
}
Response.Status = "success"
res.Header().Set("Content-Type", "application/json")
rnd.JSON(res, http.StatusOK, Response)
}
My Desrired output is a json string like this
{
"Result": [
{
"brand": "Hero Honda",
"model": "Passion Pro"
},
{
"brand": "Yamaha",
"model": "120"
},...
]
"Result1":[
{
"service_type" : "repairs",
},
{
"service_type" : "general service",
},...
]
"Result2":[
{
"b2b_repair_decription": "Tire Replacement"
},
{
"b2b_repair_decription": "Electric work"
},...
]
}
but the output which i got contains the same row instead of all the rows like
this,
{
"Result": [
{
"brand": "Yamaha",
"model": "120"
},
{
"brand": "Yamaha",
"model": "120"
},...
]
"Result1":[
{
"service_type" : "general service",
},
{
"service_type" : "general service",
},...
]
"Result2":[
{
"b2b_repair_decription": "Electric work"
},
{
"b2b_repair_decription": "Electric work"
},...
]
}
i tried appending in the loop , but it dint work. i even tried defining the Result, Result1, Result2 as array of interfaces
can someone help me with this issue?

Related

Golang - How to iterate through two slices at the same time

I'm trying to write a function that takes in a struct, and within that there are two nested structs. I need to iterate through both nested structs, find the "Service" field and remove the prefixes that are separated by the '-'.
I've written a function that does what I want it to and removes the prefixes, however it consists of two for loops that loop through the two separate structs. Is their a way for me to write this function in a way that it loops through the structs in one for loop?
Here are the structs:
var myJson = `
{
"ID": "hgfd5432",
"Greeting": "Welcome!",
"ServiceNames": [
{
"Service": "sevice-name-service1",
"Version": "1.8"
},
{
"Service": "sevice-name-service2",
"Version": "1.8"
},
{
"Service": "sevice-name-service3",
"Version": "1.9"
},
{
"Service": "sevice-name-service4",
"Version": "0.6"
}
],
"Services": [
{
"Service": "sevice-name-service5",
"Version": "1.8"
}
],
"BusinessUnit": "Unit 1",
"Queue": "UK73_Advocacy_PCCT",
"Input": "Default",
}`
type Profile struct {
ProfileId string `json:"ID"`
Input string `json:"Input"`
ParentProfile string `json:"ParentProfile"`
Persona string `json:"Persona"`
BusinessUnit string `json:"BusinessUnit"`
Greeting string `json:"Greeting"`
Queue string `json:"Queue"`
ServiceNames []ServiceKey `json:"ServiceNames"`
Services []ServiceInfo `json:"Services"`
And here is the function:
func removePrefix(inputParameters *Profile) error {
for i := 0; i < len(inputParameters.ServiceNames); i++ {
a := strings.Split(inputParameters.ServiceNames[i].Service, "-")
s := a[len(a)-1]
inputParameters.ServiceNames[i].Service = s
}
for i := 0; i < len(inputParameters.Services); i++ {
a := strings.Split(inputParameters.Services[i].Service, "-")
s := a[len(a)-1]
inputParameters.Services[i].Service = s
}
return nil
One way you can do this is,
serviceNamesLength := len(inputParameters.ServiceNames)
servicesLength := len(inputParameters.Services)
maxLength := serviceNamesLength
if servicesLength > maxLength {
maxLength = servicesLength
}
for i := 0; i < maxLength; i++ {
if i < servicesLength {
// services stuff
}
if i < serviceNamesLength {
// services names stuff
}
}
here's how you can do this,by using concurrency:
func ConcurrencyLoop(inputParameters *Profile) {
done := make(chan interface{})
var wg sync.WaitGroup
wg.Add(2)
servicesNameChan := TransformServiceNames(done, inputParameters.ServiceNames, &wg)
servicesInfoChan := TransformServiceInfo(done, inputParameters.Services, &wg)
if servicesName, ok := <-servicesNameChan; ok {
inputParameters.ServiceNames = servicesName
}
if servicesInfo, ok := <-servicesInfoChan; ok {
inputParameters.Services = servicesInfo
}
close(done)
wg.Wait()
}
func TransformServiceNames(done <-chan interface{}, servicesKey []ServiceKey, wg *sync.WaitGroup) <-chan []ServiceKey {
keysChan := make(chan []ServiceKey)
go func() {
defer wg.Done()
transformedServicekeys := make([]ServiceKey, 0)
for _, serviceKey := range servicesKey {
a := strings.Split(serviceKey.Service, "-")
s := a[len(a)-1]
transformedServicekeys = append(transformedServicekeys, ServiceKey{
Service: s,
})
}
for {
select {
case <-done:
return
case keysChan <- transformedServicekeys:
}
}
}()
return keysChan
}
func TransformServiceInfo(done <-chan interface{}, servicesKey []ServiceInfo, wg *sync.WaitGroup) <-chan []ServiceInfo {
keysChan := make(chan []ServiceInfo)
go func() {
defer wg.Done()
transformedServiceinfo := make([]ServiceInfo, 0)
for _, serviceKey := range servicesKey {
a := strings.Split(serviceKey.Service, "-")
s := a[len(a)-1]
transformedServiceinfo = append(transformedServiceinfo, ServiceInfo{
Service: s,
})
}
for {
select {
case <-done:
return
case keysChan <- transformedServiceinfo:
}
}
}()
return keysChan
}

Getting file content into a multidimensional string var

I'm using the fsnotify packet to wait for changes in a json file.
I have two problems with this code. The first one is regarding the info returned by ReadFile function. Looks like when I print something returned by the function is empty.
Second issue is regarding the fsnotify that is not reading the file the first time unless i do some modification on the content. I must read the file from the beggining as well.
type Information struct {
Info []Info `json:"info"`
}
type Info struct {
Type string `json:"type"`
News []New `json:"news"`
}
type New struct {
Name string `json:"name"`
Read bool `json:"read"`
}
func ReadFile(file_name string) *Information {
jsonFile, err := os.Open(file_name)
if err != nil {
fmt.Println(err)
}
fmt.Println("Successfully Opened file_name.json")
defer jsonFile.Close()
byteValue, _ := ioutil.ReadAll(jsonFile)
var infor Information
json.Unmarshal(byteValue, &infor)
return &infor
}
// main function
func main() {
// read json file using fsnotify to wait for changes
watcher, err := fsnotify.NewWatcher()
if err != nil {
panic(err)
}
err = watcher.Add(file_json)
if err != nil {
panic(err)
}
for {
select {
case ev, ok := <-watcher.Events:
log.Println("event:", ev)
if !ok {
return
}
if ev.Op&fsnotify.Write == fsnotify.Write {
data := ReadFile(file_name)
fmt.Print("INFORMATION ABOUT FILE:\n")
for _, info := range data.Info {
fmt.Printf("Info type: %s\n", info.Type) // Here is not printing the result of info.Type
for _, news := range info.News {
fmt.Printf("News Name: %s\n", news.Name) // Here is not printing even "News Name:" or News Read:"
fmt.Printf("News Read: %s\n", strconv.FormatBool(news.Read))
}
}
}
case err := <-watcher.Errors:
log.Println("error:", err)
}
}
}
This is the json file:
{
    "info": [
      {
        "type": "general",
        "news": [
          { "name": "abc",  "read": true },
          { "name": "def",  "read": true }
        ]
      },
{
"type": "confidential",
"news": [
{ "name": "xxx", "read": false },
{ "name": "yyy", "read": false }
]
},
]
}
type Information struct {
Info []Info `json:"info"`
}
type Info struct {
Type string `json:"type"`
News []New `json:"news"` // Here should be a slice define.
}
type New struct {
Name string `json:"name"`
Read bool `json:"read"`
}
func ReadFile(file_name string) *Information {
jsonFile, err := os.Open(file_name)
if err != nil {
fmt.Println(err)
}
fmt.Println("Successfully Opened file_name.json")
defer jsonFile.Close()
byteValue, _ := ioutil.ReadAll(jsonFile)
var infor Information
json.Unmarshal(byteValue, &infor)
return &infor
}
func main() {
data := ReadFile("./data.json")
for _, news := range data.Info {
for _, v := range news.News {
name := v.Name
// Add you want to do
fmt.Println(name)
}
}
}
You can not get like this:
getInfo = [general][abc, true, def, true]
[confidential][xxx, false, yyy, false]

Recursively changing arrays to non-arrays in JSON with sjson in Golang

What I'm trying to do:
Transform all arrays of length 1 in a JSON file to non arrays.
e.g.
Input: {"path": [{"secret/foo": [{"capabilities": ["read"]}]}]}
Output: {"path": {"secret/foo": {"capabilities": "read"}}}
I can't use Structs as the JSON format will vary...
Right now I've managed to at least detect the 1 length slices:
package main
import (
"encoding/json"
"fmt"
)
func findSingletons(value interface{}) {
switch value.(type) {
case []interface{}:
if len(value.([]interface{})) == 1 {
fmt.Println("1 length array found!", value)
}
for _, v := range value.([]interface{}) {
findSingletons(v)
}
case map[string]interface{}:
for _, v := range value.(map[string]interface{}) {
findSingletons(v)
}
}
}
func removeSingletonsFromJSON(input string) {
jsonFromInput := json.RawMessage(input)
jsonMap := make(map[string]interface{})
err := json.Unmarshal([]byte(jsonFromInput), &jsonMap)
if err != nil {
panic(err)
}
findSingletons(jsonMap)
fmt.Printf("JSON value of without singletons:%s\n", jsonMap)
}
func main() {
jsonParsed := []byte(`{"path": [{"secret/foo": [{"capabilities": ["read"]}]}]}`)
removeSingletonsFromJSON(string(jsonParsed))
fmt.Println(`Should have output {"path": {"secret/foo": {"capabilities": "read"}}}`)
}
Which outputs
1 length array found! [map[secret/foo:[map[capabilities:[read]]]]]
1 length array found! [map[capabilities:[read]]]
1 length array found! [read]
JSON value of without singletons:map[path:[map[secret/foo:[map[capabilities:[read]]]]]]
Should have output {"path": {"secret/foo": {"capabilities": "read"}}}
But I'm not sure how I can change them into non-arrays...
The type switch is your friend:
switch t := v.(type) {
case []interface{}:
if len(t) == 1 {
data[k] = t[0]
And you may use recursion to remove inside elements, like so:
func removeOneElementSlice(data map[string]interface{}) {
for k, v := range data {
switch t := v.(type) {
case []interface{}:
if len(t) == 1 {
data[k] = t[0]
if v, ok := data[k].(map[string]interface{}); ok {
removeOneElementSlice(v)
}
}
}
}
}
I would do this to convert
{"path":[{"secret/foo":[{"capabilities":["read"]}]}]}
to
{"path":{"secret/foo":{"capabilities":"read"}}}:
package main
import (
"encoding/json"
"fmt"
"log"
)
func main() {
s := `{"path":[{"secret/foo":[{"capabilities":["read"]}]}]}`
fmt.Println(s)
var data map[string]interface{}
if err := json.Unmarshal([]byte(s), &data); err != nil {
panic(err)
}
removeOneElementSlice(data)
buf, err := json.Marshal(data)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(buf)) //{"a":"a","n":7}
}
func removeOneElementSlice(data map[string]interface{}) {
for k, v := range data {
switch t := v.(type) {
case []interface{}:
if len(t) == 1 {
data[k] = t[0]
if v, ok := data[k].(map[string]interface{}); ok {
removeOneElementSlice(v)
}
}
}
}
}

empty json array is returned when the row doesn't exists in DB

my function receives a http request and sends back json string as http response.
This is my Code:
func homePage(res http.ResponseWriter, req *http.Request) {
type Resp struct {
Result []map[string]interface{} `json:"result,omitempty"`
Status string `json:"status"`
}
type Inputs struct {
ShopID string `json:"ShopID"`
DeviceID string `json:"DeviceID"`
EmpID string `json:"EmpID"`
Token string `json:"Token"`
Version string `json:"Version"`
}
var Response Resp
Response.Status = "failed"
db, err := sql.Open("mysql", "root:password#tcp(127.0.0.1:3306)/b2b")
if err != nil {
panic(err.Error())
}
defer db.Close()
rnd := render.New()
b, err := ioutil.ReadAll(req.Body)
defer req.Body.Close()
if err != nil {
panic(err.Error())
}
// Unmarshal the request body
var msg Inputs
err = json.Unmarshal(b, &msg)
if err != nil {
panic(err.Error())
}
bookingrows, bookingerr := db.Query("SELECT DISTINCT b2b_booking_id,b2b_check_in_report,b2b_vehicle_at_garage,b2b_service_under_progress,b2b_vehicle_ready,b2b_vehicle_delivered FROM b2b_booking_tbl WHERE b2b_flag=0 and b2b_shop_id=?", msg.ShopID)
if bookingerr != nil {
panic(bookingerr.Error())
} else {
Result := make(map[string]interface{})
for bookingrows.Next() {
var bookingid, checkinreported, vehicleingarage, serviceinprogress, vehicleready, vehicledelivered string
err = bookingrows.Scan(&bookingid, &checkinreported, &vehicleingarage, &serviceinprogress, &vehicleready, &vehicledelivered)
type Output struct {
checkins int `json:"checkins"`
inprogress int `json:"inprogress"`
ready int `json:"ready"`
completed int `json:"completed"`
}
var output Output
if err != nil {
panic(err.Error())
Response.Status = "failed"
}
if vehicledelivered == "1" {
output.completed = output.completed + 1
}
if vehicledelivered == "0" && vehicleready == "1" {
output.ready = output.ready + 1
}
if vehicledelivered == "0" && vehicleready == "0" && serviceinprogress == "1" {
output.inprogress = output.inprogress + 1
}
if vehicledelivered == "0" && vehicleready == "0" && serviceinprogress == "0" && (checkinreported == "1" || vehicleingarage == "1") {
output.checkins = output.checkins + 1
}
values := make([]string, 4)
val := reflect.ValueOf(output)
for i := range values {
//Result[usercolumns[i]] = fmt.Sprintf("%s", v)
Result[val.Type().Field(i).Tag.Get("json")] = fmt.Sprintf("%v", i)
}
}
Response.Result = append(Response.Result, Result)
Response.Status = "success"
}
res.Header().Set("Content-Type", "application/json")
rnd.JSON(res, http.StatusOK, Response)
}
Im getting the desired output when the input values are correct and the corresponding row exists in Db. but when the input is wrong or the query fails, i should return only the status as "failed" but my output contains the result [] which is empty like this.
{
"result": [
{}
],
"status": "success"
}
I tried checking Result == nil and add the array only on true. but this doesn't help me. it might be because the struct is not nill.
I need some help to to find the issue and solve it.
Trying checking the length of the Result array before appending it to output
Something like this
if (len(Result) != 0) {
Response.Result = append(Response.Result, Result)
}
Maybe you also need to write this also Result := make(map[string]interface{}) inside the if condition, before the append statement

martini & appengine/golang, return memcached JSON data

I am now coding with Martini and AppEngine/Go.
I want to use memcache to serve JSON data.
But the response is invalid JSON format.Why "null" is in the response?
null{"results":[{"Title":"Nikkei225","PriceTime":"2014-04-25 06:28:00 UTC","Price":"14,429.26","Diff":"+24.27(0.1%)"},{"Title":"USD/JPY","PriceTime":"2014-04-25 20:49:00 UTC","Price":"102.12-102.16","Diff":"-0.15(-0.1%)"},{"Title":"EURO/JPY","PriceTime":"2014-04-25 20:49:00 UTC","Price":"141.28-141.32","Diff":"-0.19(-0.1%)"},{"Title":"EURO/USD","PriceTime":"2014-04-25 20:48:00 UTC","Price":"1.3833-1.3836","Diff":"+0.0002(0.0%)"},{"Title":"USD/CNY","PriceTime":"2014-04-25 20:48:00 UTC","Price":"6.2536-6.2546","Diff":"+0.0063(0.1%)"},{"Title":"DJIA","PriceTime":"2014-04-25 07:29:00 UTC","Price":"16,361.46","Diff":"-140.19(-0.8%)"},{"Title":"Nasdaq","PriceTime":"2014-04-25 07:00:00 UTC","Price":"4,075.561","Diff":"-72.777(-1.7%)"},{"Title":"FTSE100","PriceTime":"2014-04-25 07:35:00 UTC","Price":"6,685.69","Diff":"-17.31(-0.2%)"}]}
And console says like below:
http: multiple response.WriteHeader calls
My code is like below.
Retrieve from cache:
c := appengine.NewContext(req)
memcacheKey := "markets"
results := []Result{}
cachedItem, getCacheErr := memcache.JSON.Get(c, memcacheKey,&map[string]interface{}{"results": results})
if getCacheErr != nil && getCacheErr != memcache.ErrCacheMiss {
c.Infof("get cache error")
}
if getCacheErr == nil {
c.Infof("cached data found")
c.Infof("cached data: %v",cachedItem.Value)
r.JSON(200, cachedItem.Object)
} else {
c.Infof("cached data not found")
}
Set to memcache:
client := urlfetch.Client(c)
resp, err := client.Get("http://www.nikkei.com/markets/kaigai/worldidx.aspx")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
indexes := Indexes()
doc, _ := goquery.NewDocumentFromResponse(resp)
doc.Find("div.mk-world_market div table tr").Each(func(_ int, s *goquery.Selection) {
title := s.Find("th").Text()
title = strings.Trim(strings.Replace(title,"※","",-1)," ")
if val,ok := indexes[title]; ok {
price := s.Find("th").Next().Text()
diff := s.Find("td:nth-child(3)").Text()
pricetime := s.Find("td:nth-child(4)").Text()
t := time.Now()
pricetime = StringToTime(pricetime,t)
result := Result{val,pricetime,price,diff}
results = append(results,result)
}
})
item := &memcache.Item{
Key:memcacheKey,
Object: &map[string]interface{}{"results": results},
}
setErr := memcache.JSON.Set(c, item)
if setErr != nil {
c.Infof("set error: %v",setErr)
}
What is wrong with my code?
self-resolution:
What I want to do is below.
m.Get("/api/Markets", func(w http.ResponseWriter,r render.Render,req *http.Request) {
c := appengine.NewContext(req)
memcache_key := "markets"
var item_list []Result
results := []Result{}
_, get_cache_err := memcache.JSON.Get(c,memcache_key,&item_list)
if get_cache_err != nil && get_cache_err != memcache.ErrCacheMiss {
c.Infof("get cache error")
}
if get_cache_err == nil {
c.Infof("cached data found")
c.Infof("cached data: %v",item_list)
results = item_list
} else {
c.Infof("cached data not found")
client := urlfetch.Client(c)
resp, err := client.Get("http://www.nikkei.com/markets/kaigai/worldidx.aspx")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
indexes := Indexes()
doc, _ := goquery.NewDocumentFromResponse(resp)
doc.Find("div.mk-world_market div table tr").Each(func(_ int, s *goquery.Selection) {
title := s.Find("th").Text()
title = strings.Trim(strings.Replace(title,"※","",-1)," ")
if val,ok := indexes[title]; ok {
price := s.Find("th").Next().Text()
diff := s.Find("td:nth-child(3)").Text()
pricetime := s.Find("td:nth-child(4)").Text()
t := time.Now()
pricetime = StringToTime(pricetime,t)
result := Result{val,pricetime,price,diff}
results = append(results,result)
}
})
item_list = results
item := &memcache.Item{
Key:memcache_key,
Object: &item_list,
}
setErr := memcache.JSON.Set(c, item)
if setErr != nil {
c.Infof("set error: %v",setErr)
}
}
r.JSON(200, map[string]interface{}{"results": item_list})
})

Resources