Camille BOUQUET
Camille BOUQUET

Reputation: 423

How to save a JSON file into csv

I am trying to save this astros.json file into csv file.

Everything is working I don't have any error but my code is not going into my for loop.

So the astros.csv file is created successfully but there are no datas inside.

package main

import (
    "encoding/json"
    "encoding/csv"
    "fmt"
    "io/ioutil"
    "os"
    "net/http"
    "strconv"
)

type People struct {
    Name string
    Craft string
}

type General struct {
    //People []People
    Number int
    Message string
}

func main() {
    // Reading data from JSON File  
    response, err := http.Get("http://api.open-notify.org/astros.json")
    if err != nil {
        fmt.Printf("The Http request failed with error %s\n", err)
    }

    data,_ := ioutil.ReadAll(response.Body)
    //fmt.Println(string(data))
    // Unmarshal JSON data
    var general []General
    json.Unmarshal([]byte(data), &general)
    //fmt.Printf("First person: %s, Message: %s", general.People[0].Name, general.Message)

    // Create a csv file
    csvdatafile, err := os.Create("./astros.csv")
    if err != nil {
        fmt.Println(err)
    }
    defer csvdatafile.Close()
    // Write Unmarshaled json data to CSV file
    w := csv.NewWriter(csvdatafile)
    for _, obj := range general {   
        fmt.Println("Are you going into the for ?")
        var record []string
        //record = append(record, obj.People)
        record = append(record, strconv.Itoa(obj.Number), obj.Message)
        record = append(record, obj.Message)
        //record = append(record, []string{People})
        w.Write(record)
        fmt.Println("Are you coming here")
        record = nil
    }
    w.Flush()
    fmt.Println("Appending succed")

}

Upvotes: 0

Views: 94

Answers (2)

Brits
Brits

Reputation: 18334

It is important to always check for errors; if you change your code to:

err = json.Unmarshal([]byte(data), &general)
if err != nil {
   fmt.Printf("Error in unmarshall %s\n", err)
   return
}

Then you would see the problem; json.Unmarshal is returning cannot unmarshal object into Go value of type []main.General. This means that general is nil so your loop is never entered.

The reason for this is apparent when you compare the JSON:

{
    "people": [{
            "name": "Christina Koch",
            "craft": "ISS"
        }, {
            "name": "Alexander Skvortsov",
            "craft": "ISS"
        }, {
            "name": "Luca Parmitano",
            "craft": "ISS"
        }, {
            "name": "Andrew Morgan",
            "craft": "ISS"
        }, {
            "name": "Oleg Skripochka",
            "craft": "ISS"
        }, {
            "name": "Jessica Meir",
            "craft": "ISS"
        }
    ],
    "number": 6,
    "message": "success"
}

With the variable you are unmarshalling into; []General where General is:

type General struct {
    //People []People
    Number int
    Message string
}

It looks like you had the right idea at some point with the []People but then commented it out.

If you uncomment []People, unmarshal into a General (rather than []General) then make your loop for _, obj := range general.People { it should work as expected. This assumes that you want to iterate through the people; general.Message and general.Number are also available (but you dont need a loop to access these).

See this example (have removed file operation as the playground does not support that).

Upvotes: 1

andre
andre

Reputation: 447

you could try something like this:

package main

import (
    "encoding/csv"
    "encoding/json"
    "fmt"
    "net/http"
    "os"
    "strconv"
)

type People struct {
    Name  string
    Craft string
}

type Response struct {
    People  []People
    Number  int
    Message string
}

func main() {
    // Reading data from JSON File
    r, err := http.Get("http://api.open-notify.org/astros.json")
    if err != nil {
        fmt.Printf("The Http request failed with error %s\n", err)
    }

    var response Response
    err = json.NewDecoder(r.Body).Decode(&response)
    if err != nil {
        fmt.Printf("decoding error%s\n", err)
        return
    }

    // Create a csv file
    csvdatafile, err := os.Create("./astros.csv")
    if err != nil {
        fmt.Println(err)
    }
    defer csvdatafile.Close()
    // Write Unmarshaled json data to CSV file
    w := csv.NewWriter(csvdatafile)
    for _, obj := range response.People {
        fmt.Println("Are you going into the for ?")
        var record []string

        //record = append(record, obj.People)
        record = append(record, strconv.Itoa(response.Number), response.Message)
        record = append(record, obj.Name)
        // record = append(record, []string{obj})
        w.Write(record)
        fmt.Println("Are you coming here")
        record = nil
    }
    w.Flush()
    fmt.Println("Appending succed")

}

Upvotes: 0

Related Questions