2

I am trying to Parse Json & Print Data and save in a CSV using GO language .

It is printing the desired 10 result per page with Println but couldn't parse JSON .

This is what I am doing

  1. Visitor visits studentresults.com/page=1 RollNo. & Marks for 10 students are displayed and it is also saved in a CSV [key.rollno & key.marks]

  2. Program Makes a request to studentsapimarks.com/api/rollno1,rollno2,rollno3/detail (appending all key.rollno that we got in step1) The Json response would be like

    [{"name":"James","Percentage":96.5,"Remarks":"VeryGood"}, 
    {"name":"William","Percentage":36.0,"Remarks":"Bad"}, 
    {"name":"Jacob","Percentage":63.0,"Remarks":"Average"}, 
    {"name":"Wilson","Percentage":69.3,"Remarks":"Average"}, 
    {"name":"Kurtson","Percentage":16.9,"Remarks":"VeryBad"}, 
    {"name":"Tom","Percentage":86.3,"Remarks":"Good"}]
    
  3. Extract Name & Percentage fields & save in a csv

Here is my snippet of the code that is responsible for printing and saving the results

package main

import (
    "encoding/csv"
    "fmt"
    "net/http"
    "os"
    "strings"
    "encoding/json"

)


type Key struct {
    fname      string
    marks      int
    rollno     int
    }

type object struct {
    Percentage float64
    Name string `json:"name"`
    }


func PageRequest(w http.ResponseWriter, r *http.Request) {


    // Page header
    fmt.Fprintf(w, PageHeader, pages, previous, next)

    // Save in csv
    csvfile, err := os.OpenFile("marks.csv", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    defer csvfile.Close()

    writer := csv.NewWriter(csvfile)
    defer writer.Flush()

    // Defining RollNos
    var rollNos []string

    // Marks for UID
    UID, length := compute(start)
    for i := 0; i < length; i++ {
        key := UID[i]

    // Prints firstname, Marks and Rollno
        fmt.Fprintf(w, key.fname, key.marks, key.rollno) 



        records := [][]string{{key.fname, key.marks, key.rollno}}

        for _, record := range records {
            err := writer.Write(record)
            if err != nil {
                fmt.Println("Error:", err)
                return
            }
        }

    // Append All key.rollno
        rollNos := append(rollNos, key.rollno)

    // Makes a request to as studentsapimarks.com/api/rollno1,rollno2,rollno3/detail
        uri := "https://studentsapimarks.com/api/" + strings.Join(rollNos, ",") + "/detail"

        res, err := http.Get(uri)
        if err != nil {
            log.Fatal(err)
        }
        defer res.Body.Close()

        var s []object
        err = json.NewDecoder(res.Body).Decode(&s)
        if err != nil {
            log.Fatal(err)
        }

    // Prints Name/ Percentage
        fmt.Println(s[0].Name)
        fmt.Println(s[0].Percentage)
    }

    // Page Footer
    fmt.Fprintf(w, PageFooter, previous, next)
}


func main() {
    http.HandleFunc("/", PageRequest)

log.Println("Listening")
log.Fatal(http.ListenAndServe(":8080", nil))

}

fmt.Fprintf(w, key.fname, key.marks, key.rollno) is working fine and displays all 10 results per page and saves in a csv .

Problem with the code is

  1. It is not appending all key.rollno that we got in step1 as studentsapimarks.com/api/rollno1,rollno2,rollno3/detail

  2. Also how could i save the JSON extracted s[0].name results in a CSV ?

1 Answer 1

1

The JSON parsing is failing because you're trying to unmarshal a JSON array into a struct. You want to unmarshal a JSON array into a slice - the outer struct is not necessary:

var s []object
err = json.NewDecoder(res.Body).Decode(&s)

Also, it can only unmarshal exported fields (those that start with a capital letter), so to get the name, you'll need to change your struct definition. I'm guessing the percentage isn't coming through either, since in the JSON it's a single float value, but in your struct you're taking a float slice.

type object struct {
    // "Percentage": 96.4 is not a slice.
    // Also if the field name in Go and JSON are identical, you dont need the json tag.
    Percentage float64
    // The field must be capitalized, the tag can stay lowercase
    Name string `json:"name"`
}

Then you'll access those fields accordingly:

// Prints Name/ Percentage
fmt.Println(s[0].Name)
fmt.Println(s[0].Percentage)
Sign up to request clarification or add additional context in comments.

12 Comments

removed type object struct & type ObjectsAPIResponse struct and used var s []object now getting error undefined: object
That's because you removed the object type. I gave you an updated definition for it - don't remove it, use the updated definition.
now error s.Allmarks undefined (type []object has no field or method Allmarks)
Updated answer.
removed type ObjectsAPIResponse struct and used var s []object and modified fmt.Println(s.Allmarks[0].name) to fmt.Println(s.[0].name)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.