// `unpaginate` unpaginates json resources. package main import ( "encoding/json" "flag" "fmt" "net/http" "os" "strings" ) func init() { flag.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: %s [flags] \n\n", os.Args[0]) fmt.Fprintf(os.Stderr, `Fetches JSON documents from a paginated resource and returns a single JSON document. `) flag.PrintDefaults() fmt.Fprintf(os.Stderr, " -h, --help\n\tDisplay this message\n") } } func main() { flag.Parse() if flag.NArg() != 1 { flag.Usage() os.Exit(1) } url := flag.Arg(0) os.Stdout.WriteString("[\n") first := true for url != "" { res, err := http.Get(url) if err != nil { fmt.Println(err) os.Exit(1) } decoder := json.NewDecoder(res.Body) _, err = decoder.Token() if err != nil { fmt.Println(err) os.Exit(1) } for decoder.More() { if !first { os.Stdout.WriteString(", ") } else { first = false } var data interface{} err := decoder.Decode(&data) if err != nil { fmt.Println("decode:", err) os.Exit(1) } out, err := json.MarshalIndent(data, " ", " ") if err != nil { fmt.Println(err) os.Exit(1) } os.Stdout.Write(out) } _, err = decoder.Token() if err != nil { fmt.Println(err) os.Exit(1) } url = "" links := res.Header.Get("Link") if links != "" { for _, link := range strings.Split(links, ",") { link := strings.TrimSpace(link) start := strings.Index(link, "<") end := strings.Index(link, ">") if start != -1 && end != -1 && start < end && strings.HasSuffix(link, "rel=\"next\"") { url = link[start+1 : end] break } } } } os.Stdout.WriteString("\n]\n") }