为了账号安全,请及时绑定邮箱和手机立即绑定

在服务器上加载 CSV 数据,将数据转换为 JSON 并使用 Golang 使用 Json

在服务器上加载 CSV 数据,将数据转换为 JSON 并使用 Golang 使用 Json

Go
饮歌长啸 2022-06-27 15:15:59
我正在尝试构建一个 TCP 服务器,它从CSV文件加载数据集并提供一个接口来查询数据集。TCP 服务器将暴露 4040 端口。 CSV 文件包含与冠状病毒病例相关的以下列:累积测试阳性进行的累积测试日期出院已到期录取区域用户应该能够在基于 Linux/Unix 的系统上使用NetCat命令连接到服务器。 nc localhost 4040一旦连接到 TCP,用户应该能够通过发送 JSON 格式的查询与应用程序进行通信。{    "query": {        "region": "Sindh"    }}{    "query": {        "date": "2020-03-20"    }}这会正确加载 csv 并将其转换为 JSON。但是,当我尝试使用 NetCat 命令运行查询时,它返回空 JSON 元素。请指导我哪里出错了。
查看完整描述

2 回答

?
翻过高山走不出你

TA贡献1875条经验 获得超3个赞

猜你想要这个:


╭─root@DESKTOP-OCDRD7Q ~

╰─# nc localhost 4040

{"get": "Sindh"}

[{"Covid_Positive":"1","Coivd_Performed":"1","Covid_Date":"1","Covid_Discharged":"1","Covid_Expired":"1","Covid_Region":"Sindh","Covid_Admitted":"1"}]

您应该做的只是修改您的 json 请求。


package main


import (

    "bufio"

    "encoding/csv"

    "encoding/json"

    "flag"

    "fmt"

    "io"

    "log"

    "net"

    "os"

)


type CovidPatient struct {

    Positive   string `json:"Covid_Positive"`

    Performed  string `json:"Coivd_Performed"`

    Date       string `json:"Covid_Date"`

    Discharged string `json:"Covid_Discharged"`

    Expired    string `json:"Covid_Expired"`

    Region     string `json:"Covid_Region"`

    Admitted   string `json:"Covid_Admitted"`

}


type DataRequest struct {

    Get CovidPatient `json:"get"`

}


type DataError struct {

    Error string `json:"Covid_error"`

}


func Load(path string) []CovidPatient {

    table := make([]CovidPatient, 0)

    var patient CovidPatient

    file, err := os.Open(path)

    if err != nil {

        panic(err.Error())

    }

    defer file.Close()


    reader := csv.NewReader(file)

    csvData, err := reader.ReadAll()

    if err != nil {

        fmt.Println(err)

        os.Exit(1)

    }

    for _, row := range csvData {

        patient.Positive = row[0]

        patient.Performed = row[1]

        patient.Date = row[2]

        patient.Discharged = row[3]

        patient.Expired = row[4]

        patient.Region = row[5]

        patient.Admitted = row[6]

        table = append(table, patient)

    }

    return table

}


func Find(table []CovidPatient, filter CovidPatient) []CovidPatient {


    result := make([]CovidPatient, 0)


    log.Println(filter, table)


    for _, cp := range table {


        if filter.Positive == "" {

        } else if filter.Positive != cp.Positive {

            continue

        }

        if filter.Performed == "" {

        } else if filter.Performed != cp.Performed {

            continue

        }

        if filter.Date == "" {

        } else if filter.Date != cp.Date {

            continue

        }

        if filter.Discharged == "" {

        } else if filter.Discharged != cp.Discharged {

            continue

        }

        if filter.Expired == "" {

        } else if filter.Expired != cp.Expired {

            continue

        }

        if filter.Region == "" {

        } else if filter.Region != cp.Region {

            continue

        }

        if filter.Admitted == "" {

        } else if filter.Admitted != cp.Admitted {

            continue

        }


        result = append(result, cp)

    }

    return result


}


var (

    patientsDetail = Load("./covid_final_data.csv")

)


func main() {

    log.SetFlags(log.Lshortfile | log.Ltime)

    var addr string

    var network string

    flag.StringVar(&addr, "e", ":4040", "service endpoint [ip addr or socket path]")

    flag.StringVar(&network, "n", "tcp", "network protocol [tcp,unix]")

    flag.Parse()


    switch network {

    case "tcp", "tcp4", "tcp6", "unix":

    default:

        fmt.Println("unsupported network protocol")

        os.Exit(1)

    }


    ln, err := net.Listen(network, addr)

    if err != nil {

        log.Println(err)

        os.Exit(1)

    }

    defer ln.Close()

    log.Println("Covid19 Condition in Pakistan")

    log.Printf("Service started: (%s) %s\n", network, addr)


    for {

        conn, err := ln.Accept()

        if err != nil {

            log.Println(err)

            conn.Close()

            continue

        }

        log.Println("Connected to ", conn.RemoteAddr())

        go handleConnection(conn)

    }

}

func handleConnection(conn net.Conn) {

    defer func() {

        if err := conn.Close(); err != nil {

            log.Println("error closing connection:", err)

        }

    }()


    reader := bufio.NewReaderSize(conn, 100)


    for {

        buf, err := reader.ReadBytes('|')

        if err != nil {

            if err != io.EOF {

                log.Println("connection read error:", err)

                return

            }

        }

        reader.Reset(conn)


        var req DataRequest

        if err := json.Unmarshal(buf[:len(buf)-1], &req); err != nil {

            log.Println("failed to unmarshal request:", string(buf), err)

            cerr, jerr := json.Marshal(DataError{Error: err.Error()})

            if jerr != nil {

                log.Println("failed to marshal DataError:", jerr)

                continue

            }

            if _, werr := conn.Write(cerr); werr != nil {

                log.Println("failed to write to DataError:", werr)

                return

            }

            continue

        }


        result := Find(patientsDetail, req.Get)


        rsp, err := json.Marshal(&result)

        if err != nil {

            log.Println("failed to marshal data:", err)

            if _, err := fmt.Fprintf(conn, `{"data_error":"internal error"}`); err != nil {

                log.Printf("failed to write to client: %v", err)

                return

            }

            continue

        }

        if _, err := conn.Write(rsp); err != nil {

            log.Println("failed to write response:", err)

            return

        }

    }

}


查询是:


╭─root@DESKTOP-OCDRD7Q ~

╰─# nc localhost 4040                                                                                             127 ↵

{

    "get": {

        "Covid_Region": "Sindh",

        "Covid_Date": "2020-03-20"

    }

}|

[{"Covid_Positive":"1","Coivd_Performed":"1","Covid_Date":"2020-03-20","Covid_Discharged":"1","Covid_Expired":"1","Covid_Region":"Sindh","Covid_Admitted":"1"}]



查看完整回答
反对 回复 2022-06-27
?
回首忆惘然

TA贡献1847条经验 获得超11个赞

在 functionhandleConnection中,第一件事是“读取直到找到第一个}”,假设用户正在发送请求:


{ "get": { "Covid_Region": "Sindh", "Covid_Date": "2020-03-20" } }

然后该步骤如下:


{ "get": { "Covid_Region": "Sindh", "Covid_Date": "2020-03-20" }

}请注意缺少尾随,然后json.Unmarshal尝试在没有最后一个的情况下解组查询}(这是无效的 json)。


这个问题可以利用 JSON 流解码,换句话说,使用json.NewDecoder(r io.Reader)代替json.Unmarshal. 让我复制并修改该函数的第一部分:


func handleConnection(conn net.Conn) {

    defer func() {

        if err := conn.Close(); err != nil {

            log.Println("error closing connection:", err)

        }

    }()


    jsonDecoder := json.NewDecoder(conn) // A json decoder read a stream to find a

                                         // valid JSON and stop just the byte

                                         // after the JSON ends. Process can be

                                         // repeated.


    for {

        var req DataRequest

        err := jsonDecoder.Decode(&req)

        if err == io.EOF {

            log.Println("finish")

            return

        }

        if err != nil {

            log.Println("unmarshal:", err)

            return

        }


        result := Find(patientsDetail, req.Get) // Here query the system


        // ... 


可能现在它可以工作了,但是您也可以利用 json 流通过jsonEncoder := json.NewEncoder(conn)before de for 循环发送回响应,并像这样发送请求:


        err := jsonEncoder.Encode(&result)

        if err != nil {

            log.Println("failed to marshal data:", err)

            // ...

            continue

        }


查看完整回答
反对 回复 2022-06-27
  • 2 回答
  • 0 关注
  • 178 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信