package main
import (
"bytes"
"compress/zlib"
"database/sql"
"encoding/json"
"fmt"
"io/ioutil"
"log"
_ "github.com/go-sql-driver/mysql"
"strconv"
"encoding/csv"
"os"
)
var (
data []byte
)
type UserStatsData struct {
Dates map[string]Info `json:"d"`
}
type Info struct {
Date string `json:"-"`
Gold int `json:"g"`
Revenue json.Number `json:"r"`
}
func main() {
db, err := sql.Open("mysql", "name:password(127.0.0.1:port)/database")
if err != nil {
panic(err.Error())
}
defer db.Close()
rows, err := db.Query(`SELECT data FROM user_stats ORDER BY created_at LIMIT 2`)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
file, err := os.Create("result.csv")
if err != nil {
fmt.Println(err)
}
defer file.Close()
userStatsData := UserStatsData{}
cont := 0
writer := csv.NewWriter(file)
for rows.Next() {
err := rows.Scan(&data)
if err != nil {
log.Fatal(err)
}
if err := json.Unmarshal(data, &userStatsData); err != nil {
r, err := zlib.NewReader(bytes.NewReader(data))
if err != nil {
log.Panicf("\nCannot read archive %v", err)
}
r.Close()
data, _ = ioutil.ReadAll(r)
}
parsed := make(map[string]interface{})
if err := json.Unmarshal(data, &parsed); err != nil {
panic(err.Error())
}
var info []Info
for _, elem := range info {
previousValue, ok := parsed[elem.Date]
if ok {
parsed[elem.Date] = previousValue + elem.Gold
} else {
parsed[elem.Date] = elem.Gold
}
}
for _, i := range info {
if cont == 0 {
var record []string
record = append(record, "Date")
record = append(record, "Gold")
record = append(record, "Revenue")
writer.Write(record)
cont++
}
var record []string
record = append(record, i.Date)
record = append(record, strconv.Itoa(i.Gold))
record = append(record, i.Revenue.String())
writer.Write(record)
cont++
}
writer.Flush()
err = writer.Error()
if err != nil {
panic(err)
}
}
}
var info []Info
for _, elem := range info {
Ну и пример данных бы не мешало увидеть. Что в архиве, что не в архиве.
date := parsed["d"].(map[string]interface{})
for k, v := range date {
switch vv := v.(type) {
case string:
fmt.Println(k, vv)
}
}
gold := parsed["d"][k]["g"].(map[string]interface{})
Нет, мне не надо чтоб кто-то сделал за меня код, мне нужна помощь всего лишь в понимании.
var userStatsData UserStatsData var userStatsDataArchive UserStatsData if err := json.Unmarshal([]byte(dbRowData), &userStatsData); err != nil {
if err != nil { log.Panicf("\nCannot read archive %v", err) } }
if err := json.Unmarshal([]byte(archiveData), &userStatsDataArchive); err != nil { panic(err.Error()) } parsed := make(map[string]Info) for k, v := range userStatsDataArchive.Dates { if item, ok := parsed[k]; ok { item.Gold += v.Gold item.Revenue += v.Revenue parsed[k] = item } else { parsed[k] = v } fmt.Println("parsed archive: ", k, ": ", v) } for k, v := range userStatsData.Dates { if item, ok := parsed[k]; ok { item.Gold += v.Gold item.Revenue += v.Revenue parsed[k] = item } else { parsed[k] = v } fmt.Println("parsed: ", k, ": ", v) } var records [][]string var record []string for k, v := range parsed { record = append(record, k) record = append(record, string(v.Gold)) record = append(record, fmt.Sprintf("%.2f", v.Revenue)) writer.Write(record) } writer.Flush()
package main
import (
"bytes"
"compress/zlib"
"database/sql"
"encoding/json"
"fmt"
"io/ioutil"
"log"
_"github.com/go-sql-driver/mysql"
"encoding/csv"
"os"
)
var (
data []byte
)
type UserStatsData struct {
Dates map[string]Info `json:"d"`
}
type Info struct {
Date string `json:"-"`
Gold int `json:"g"`
Revenue float64 `json:"r"`
}
func main() {
db, err := sql.Open("mysql", "name:password@tcp(127.0.0.1:port)/database")
if err != nil {
panic(err.Error())
}
defer db.Close()
rows, err := db.Query(`SELECT data FROM user_stats ORDER BY created_at LIMIT 2`)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
file, err := os.Create("result.csv")
if err != nil {
fmt.Println(err)
}
defer file.Close()
userStatsData := UserStatsData{}
cont := 0
writer := csv.NewWriter(file)
for rows.Next() {
err := rows.Scan(&data)
if err != nil {
log.Fatal(err)
}
if err := json.Unmarshal(data, &userStatsData); err != nil {
r, err := zlib.NewReader(bytes.NewReader(data))
if err != nil {
log.Panicf("\nCannot read archive %v", err)
}
r.Close()
data, _ = ioutil.ReadAll(r)
}
if err := json.Unmarshal(data, &userStatsData); err != nil {
panic(err.Error())
}
parsed := make(map[string]Info)
for k, v := range userStatsData.Dates {
if item, ok := parsed[k]; ok {
item.Gold += v.Gold
item.Revenue += v.Revenue
parsed[k] = item
} else
{
parsed[k] = v
}
fmt.Println(k, v)
}
for k, v := range parsed {
if cont == 0 {
var record []string
record = append(record, "Date")
record = append(record, "Gold")
record = append(record, "Revenue")
writer.Write(record)
cont++
}
var record []string
record = append(record, k)
record = append(record, string(v.Gold))
record = append(record, fmt.Sprintf("%.2f", v.Revenue))
writer.Write
(record)
cont++
}
writer.Flush()
}
}
Евгений, спасибо большое Вам за помощь. Я переделал код так как должен быть, но все равно не то что надо. Вот вывод терминала:
я думаю все же он должен выглядеть вот так
package mainimport ("bytes""compress/zlib""database/sql"
)type UserStatsData struct {Dates map[string]Info `json:"d"`}type Info struct {Date string `json:"-"`Gold int `json:"g"`Revenue float64 `json:"r"`}func main() {
var data []byte
db, err := sql.Open("mysql", "name:password@tcp(127.0.0.1:port)/database")if err != nil {panic(err.Error())}defer db.Close()rows, err := db.Query(`SELECT data FROM user_stats ORDER BY created_at LIMIT 2`)if err != nil {log.Fatal(err)}defer rows.Close()file, err := os.Create("result.csv")if err != nil {fmt.Println(err)}defer file.Close()
writer := csv.NewWriter(file)
var record []stringrecord = append(record, "Date")record = append(record, "Gold")record = append(record, "Revenue")writer.Write(record)
writer.Flush()
for rows.Next() {err := rows.Scan(&data)if err != nil {log.Fatal(err)}
var userStatsData UserStatsDatavar userStatsDataArchive UserStatsData
if err := json.Unmarshal(data, &userStatsData); err != nil {r, err := zlib.NewReader(bytes.NewReader(data))if err != nil {log.Panicf("\nCannot read archive %v", err)}r.Close()data, _ = ioutil.ReadAll(r)}
if err := json.Unmarshal(data, &userStatsDataArchive); err != nil {
panic(err.Error())}parsed := make(map[string]Info)
for k, v := range userStatsDataArchive.Dates {
if item, ok := parsed[k]; ok {item.Gold += v.Golditem.Revenue += v.Revenueparsed[k] = item} else {parsed[k] = v}}for k, v := range userStatsData.Dates {if item, ok := parsed[k]; ok {item.Gold += v.Golditem.Revenue += v.Revenueparsed[k] = item} else {parsed[k] = v}}
for k, v := range parsed {
var record []stringrecord = append(record, k)record = append(record, string(v.Gold))record = append(record, fmt.Sprintf("%.2f", v.Revenue))writer.Write(record)}
Опять же, если я правильно понимаю задачу
writer.Flush()}}
И все же я думаю надо parsed разобрать на d, потом дату g, r ложить в другие map и потом делать цикл по ключам и складывать в csv. Но вот как реализовать, мне пока сложно.
if err := json.Unmarshal(data, &userStatsData); err != nil {
r, err := zlib.NewReader(bytes.NewReader(data)) if err != nil { log.Panicf("\nCannot read archive %v", err) } r.Close() data, _ = ioutil.ReadAll(r) }
if err := json.Unmarshal(data, &userStatsDataArchive); err != nil { panic(err.Error()) }
Все верно это BLOB архивный JSON
Да, я же делаю запрос sql с лимитом 2, а могу 10 и более поставить, и там могут быть хаотично как архивные так и текстовые JSON данные, и архив мне нужно декодить чтоб все на выходе был текст и с него брать d, g, r
package main
import ( "bytes" "compress/zlib" "database/sql"
)
type UserStatsData struct { Dates map[string]Info `json:"d"`}
type Info struct { Date string `json:"-"` Gold int `json:"g"` Revenue float64 `json:"r"`}
func main() {
var data []byte
db, err := sql.Open("mysql", "name:password@tcp(127.0.0.1:port)/database")
if err != nil { panic(err.Error()) } defer db.Close()
rows, err := db.Query(`SELECT data FROM user_stats ORDER BY created_at LIMIT 2`) if err != nil { log.Fatal(err) } defer rows.Close()
file, err := os.Create("result.csv") if err != nil { fmt.Println(err) } defer file.Close()
writer := csv.NewWriter(file)
var record []string record = append(record, "Date") record = append(record, "Gold") record = append(record, "Revenue") writer.Write(record)
var userStatsDataArr []UserStatsData var userStatsDataArchiveArr []UserStatsData
for rows.Next() { err := rows.Scan(&data) if err != nil { log.Fatal(err) }
var userStatsData UserStatsData var userStatsDataArchive UserStatsData
err = json.Unmarshal(data, &userStatsData) if err != nil {
r, err := zlib.NewReader(bytes.NewReader(data)) if err != nil { log.Panicf("\nCannot read archive %v", err) }
defer r.Close() data, _ = ioutil.ReadAll(r) err = json.Unmarshal(data, &userStatsDataArchive)
if err != nil { panic(err.Error()) }
userStatsDataArchiveArr = append(userStatsDataArchiveArr, userStatsDataArchive) } else { userStatsDataArr = append(userStatsDataArr, userStatsData)
}
} parsed := make(map[string]Info)
for _, arch := range userStatsDataArchiveArr { for k, v := range arch.Dates {
if item, ok := parsed[k]; ok { item.Gold += v.Gold item.Revenue += v.Revenue parsed[k] = item } else { parsed[k] = v }
} }
for _, user := range userStatsDataArr { for k, v := range user.Dates {
if item, ok := parsed[k]; ok { item.Gold += v.Gold item.Revenue += v.Revenue parsed[k] = item } else { parsed[k] = v }
} }
for k, v := range parsed {
var record []string record = append(record, k) record = append(record, string(v.Gold)) record = append(record, fmt.Sprintf("%.2f", v.Revenue)) writer.Write(record) }
writer.Flush()}
Вернее не Revenue а Gold колонка не выводится
package main
import (
"bytes"
"compress/zlib"
"database/sql"
"encoding/csv"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"os"
_ "github.com/go-sql-driver/mysql"
"strconv"
)
type UserStatsData struct {
Dates map[string]Info `json:"d"`
}
type Info struct {
Date string `json:"-"`
Gold int `json:"g"`
Revenue float64 `json:"r"`
}
func main() {
var data []byte
db, err := sql.Open("mysql", "app:reACT4141@tcp(127.0.0.1:9011)/pmvalor")
if err != nil {
panic(err.Error())
}
defer db.Close()
rows, err := db.Query(`SELECT data FROM user_stats ORDER BY created_at LIMIT 2`)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
file, err := os.Create("result.csv")
if err != nil {
fmt.Println(err)
}
defer file.Close()
writer := csv.NewWriter(file)
var record []string
record = append(record, "Date")
record = append(record, "Gold")
record = append(record, "Revenue")
writer.Write(record)
writer.Flush()
var userStatsDataArr []UserStatsData
var userStatsDataArchiveArr []UserStatsData
for rows.Next() {
err := rows.Scan(&data)
if err != nil {
log.Fatal(err)
}
var userStatsData UserStatsData
var userStatsDataArchive UserStatsData
err = json.Unmarshal(data, &userStatsData)
if err != nil {
r, err := zlib.NewReader(bytes.NewReader(data))
if err != nil {
log.Panicf("\nCannot read archive %v", err)
}
record = append(record, strconv.Itoa(v.Gold))
Я ведь правильно все написал, почему оно не подсчитывает дубликаты?
вот 2 строки json и есть даты которые повторяются
{"
{"logins":[["2011-11-06",1]],"last_login":"Sun Nov 06 16:52:45 -0800 2011","d":{"2010-11-05":{"gg":0,"r":4.99,"g":0},"2011-06-22":{"gg":0,"1":{"g":100,"r":4.99},"g":100,"r":4.99},"2011-07-16":{"gg":0,"1":{"r":9.99,"g":200},"r":9.99,"g":200},"2010-11-20":{"gg":0,"r":4.99,"g":100}},"h":[{"d":"2011-06-22","wid":"1","g":100,"r":4.99},{"d":"2011-07-16","r":9.99,"g":200,"wid":"1"}],"t":{"gg":0,"1":{"g":300,"r":14.98},"r":24.96,"g":400}}
и то что выводится в csv
if err := json.Unmarshal(data, &userStatsData); err != nil {
r, err := zlib.NewReader(bytes.NewReader(data))
if err != nil {
log.Panicf("\nCannot read archive %v", err)
}
r.Close()
data, _ = ioutil.ReadAll(r)
}
parsed := make(map[string]interface{})
if err := json.Unmarshal(data, &parsed); err != nil {
panic(err.Error())
}
date := parsed["d"].(map[string]interface{})
for k, v := range date {
switch vv := v.(type) {
case string:
fmt.Println(k, vv)
}
}
gold := parsed["d"][k]["g"].(map[string]interface{})
Сначала получить занчение parsed[d] от него запросить [дата] а уже от него запросить [g] и [r]
package main
import ( "bytes" "compress/zlib" "database/sql" "encoding/csv" "encoding/json" "fmt" "io/ioutil" "log" "os"
)
type UserStatsData struct { Dates map[string]Info `json:"d"`}
type Info struct { Date string `json:"-"` Gold int `json:"g"` Revenue float64 `json:"r"`
H []Info `json:"h"`
}
func main() { var data []byte
db, err := sql.Open("mysql", "name:password@tcp(127.0.0.1:port)/database")
if err != nil { panic(err.Error()) } defer db.Close()
rows, err := db.Query(`SELECT data FROM user_stats ORDER BY created_at LIMIT 2`) if err != nil { log.Fatal(err) } defer rows.Close()
file, err := os.Create("result.csv") if err != nil { fmt.Println(err) } defer file.Close()
writer := csv.NewWriter(file) var record []string record = append(record, "Date") record = append(record, "Gold") record = append(record, "Revenue") writer.Write(record)
var userStatsDataArr []UserStatsData
for rows.Next() { err := rows.Scan(&data) if err != nil { log.Fatal(err) } var userStatsData UserStatsData
err = json.Unmarshal(data, &userStatsData) if err != nil {
r, err := zlib.NewReader(bytes.NewReader(data)) if err != nil { log.Panicf("\nCannot read archive %v", err) }
defer r.Close() data, _ = ioutil.ReadAll(r)
err = json.Unmarshal(data, &userStatsData) if err != nil {
panic(err.Error())
}
} userStatsDataArr = append(userStatsDataArr, userStatsData)
} parsed := make(map[string]Info)
for _, user := range userStatsDataArr { for k, v := range user.Dates { if item, ok := parsed[k]; ok { item.Gold += v.Gold item.Revenue += v.Revenue parsed[k] = item } else { parsed[k] = v }
for _, val := range v.H { if item, ok := parsed[val.Date]; ok { item.Gold += val.Gold item.Revenue += val.Revenue parsed[val.Date] = item } else { parsed[k] = val
Думаю что это оно, а как правильно отсортировать даты это sort.Strings()?
Если Вам не трудно, не могли бы пояснить? Спасибо.
keys := []string{}
for key, _ := range parsed {
keys = append(keys, key)
}
sort.Strings(keys)
for i := range keys {
key := keys[i]
fmt.Printf(key)
fmt.Println()
}
Вот только пока не разобрался как записать в csv
for k, v := range parsed { var record []string record = append(record, k) record = append(record, strconv.Itoa(v.Gold)) record = append(record, fmt.Sprintf("%.2f", v.Revenue)) writer.Write(record)}
for _, v := range keys{
var record []string record = append(record, v) record = append(record, strconv.Itoa(parsed[v].Gold)) record = append(record, fmt.Sprintf("%.2f", parsed[v].Revenue)) writer.Write(record)
}