package netreq import ( "bytes" "encoding/json" "fmt" "io" "net/http" "os" "path/filepath" ) // Makes a GET request to the specified URL and returns the JSON response // as a byte slice. If the request fails, it returns an error. func GetJSON[T any](url string) ([]T, error) { fmt.Println("Fetching:", url) res, err := http.Get(url) if err != nil { return nil, err } defer res.Body.Close() body, err := io.ReadAll(res.Body) if err != nil { return nil, err } if res.StatusCode > 299 { return nil, fmt.Errorf("status %d: %s", res.StatusCode, string(body)) } // 1. Trim whitespace to find the first actual JSON character trimmed := bytes.TrimSpace(body) if len(trimmed) == 0 { return nil, nil } var result []T // 2. Determine if we are looking at an Array [ ] or an Object { } if trimmed[0] == '[' { // It's already an array, unmarshal directly err = json.Unmarshal(body, &result) } else { // It's a single object, unmarshal into a single instance and wrap it var single T err = json.Unmarshal(body, &single) result = []T{single} } if err != nil { return nil, fmt.Errorf("failed to parse JSON: %w", err) } return result, nil } // Download downloads a specified object at a given url and places it in // the provided dest directory. func Download(name string, path string, url string) error { fullFilePath := filepath.Join(path, name) if err := os.MkdirAll(path, os.ModeDir); err != nil { return err } file, err := os.Create(fullFilePath) if err != nil { return err } defer file.Close() resp, err := http.Get(url) if err != nil { return err } defer resp.Body.Close() _, err = io.Copy(file, resp.Body) if err != nil { return err } return nil }