Экспорт JSON в один файл из функции цикла

Я написал код, который обращается к одному общедоступному API и сохраняет вывод JSON в файл. Но данные хранятся в файле построчно, а не в одном формате JSON.

Например.

Текущий выход:

      {"ip":"1.1.1.1", "Country":"US"}
{"ip":"8.8.8.8", "Country":"IN"}

Желаемый результат:

      [
{"ip":"1.1.1.1", "Country":"US"},
{"ip":"8.8.8.8", "Country":"IN"}
]

Я знаю, что это должно быть довольно просто, и я что-то упускаю.

Мой текущий код:

Читать IP из файла и обращаться к API по одному на каждом IP.

      func readIPfromFile(filename string, outFile string, timeout int) {
    data := jsonIn{}
    //open input file
    jsonFile, err := os.Open(filename) //open input file
    ...

    ...
    jsonData := bufio.NewScanner(jsonFile)

    for jsonData.Scan() {

        // marshal json data & check for logs
        if err := json.Unmarshal(jsonData.Bytes(), &data); err != nil {
            log.Fatal(err)
        }
        //save to file
        url := fmt.Sprintf("http://ipinfo.io/%s", data.Host)
        GetGeoIP(url, outFile, timeout)

    }
}

Сделать HTTP-запрос с настраиваемым заголовком запроса и вызвать функцию записи в файл.

      func GetGeoIP(url string, outFile string, timeout int) {
    geoClient := http.Client{
        Timeout: time.Second * time.Duration(timeout), // Timeout after 5 seconds
    }

    req, err := http.NewRequest(http.MethodGet, url, nil)
    if err != nil {
        log.Fatal(err)
    }

    req.Header.Set("accept", "application/json")

    res, getErr := geoClient.Do(req)
    if getErr != nil {
        log.Fatal(getErr)
    }

    if res.Body != nil {
        defer res.Body.Close()
    }

    body, readErr := ioutil.ReadAll(res.Body)
    if readErr != nil {
        log.Fatal(readErr)
    }

    jsonout := jsonOut{}
    jsonErr := json.Unmarshal(body, &jsonout)
    if jsonErr != nil {
        log.Fatal(jsonErr)
    }
    file, _ := json.Marshal(jsonout)
    write2file(outFile, file)
}

Чтобы записать данные в файл:

      func write2file(outFile string, file []byte) {
    f, err := os.OpenFile(outFile, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
    if err != nil {
        log.Fatal(err)
    }

    defer f.Close()
    if _, err = f.WriteString(string(file)); err != nil {
        log.Fatal(err)
    }
    if _, err = f.WriteString("\n"); err != nil {
        log.Fatal(err)
    }

Я знаю, я могу редактировать f.WriteString("\n");к f.WriteString(",");добавить запятую, но по-прежнему добавлять [] в файл для меня сложно.

1 ответ

Во-первых, пожалуйста, не изобретайте новый способ маршалинга json, просто используйте встроенный в golang encoding/jsonили другая библиотека на github.

Во-вторых, если вы хотите создать строку json, представляющую массив объектов, вам нужно создать массив объектов в golang и маршалировать его в строку (или, точнее, в массив байтов)

Я создаю простой, как показано ниже, но, пожалуйста, сделай сам, если это возможно.

https://go.dev/play/p/RR_ok-fUTb_4

Другие вопросы по тегам