Golang REST api request with token auth to json array reponse

huangapple go评论93阅读模式
英文:

Golang REST api request with token auth to json array reponse

问题

这是一个可工作的代码,如果有人发现它有用的话。这个问题的标题原本是“如何解析golang中的字典列表”。

这个标题是不正确的,因为我在引用我熟悉的Python术语。

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
)

//Regional Strut
type Region []struct {
	Region      string `json:"region"`
	Description string `json:"Description"`
	ID          int    `json:"Id"`
	Name        string `json:"Name"`
	Status      int    `json:"Status"`
	Nodes       []struct {
		NodeID    int    `json:"NodeId"`
		Code      string `json:"Code"`
		Continent string `json:"Continent"`
		City      string `json:"City"`
	} `json:"Nodes"`
}

//working request and response
func main() {
	url := "https://api.geo.com"

	// Create a Bearer string by appending string access token
	var bearer = "TOK:" + "TOKEN"

	// Create a new request using http
	req, err := http.NewRequest("GET", url, nil)

	// add authorization header to the req
	req.Header.Add("Authorization", bearer)

	//This is what the response from the API looks like
	//regionJson := `[{"region":"GEO:ABC","Description":"ABCLand","Id":1,"Name":"ABCLand [GEO-ABC]","Status":1,"Nodes":[{"NodeId":17,"Code":"LAX","Continent":"North America","City":"Los Angeles"},{"NodeId":18,"Code":"LBC","Continent":"North America","City":"Long Beach"}]},{"region":"GEO:DEF","Description":"DEFLand","Id":2,"Name":"DEFLand","Status":1,"Nodes":[{"NodeId":15,"Code":"NRT","Continent":"Asia","City":"Narita"},{"NodeId":31,"Code":"TYO","Continent":"Asia","City":"Tokyo"}]}]`
	//Send req using http Client
	client := &http.Client{}
	resp, err := client.Do(req)

	if err != nil {
		log.Println("Error on response.\n[ERROR] -", err)
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Println("Error while reading the response bytes:", err)
	}

	var regions []Region
	json.Unmarshal([]byte(body), &regions)
	fmt.Printf("Regions: %+v", regions)
}

希望对你有帮助!

英文:

EDIT
This is the working code incase someone finds it useful. The title to this question was originally
"How to parse a list fo dicts in golang".

This is title is incorrect because I was referencing terms I'm familiar with in python.

package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
)
//Regional Strut
type Region []struct {
Region      string `json:"region"`
Description string `json:"Description"`
ID          int    `json:"Id"`
Name        string `json:"Name"`
Status      int    `json:"Status"`
Nodes       []struct {
NodeID    int    `json:"NodeId"`
Code      string `json:"Code"`
Continent string `json:"Continent"`
City      string `json:"City"`
} `json:"Nodes"`
}
//working request and response
func main() {
url := "https://api.geo.com"
// Create a Bearer string by appending string access token
var bearer = "TOK:" + "TOKEN"
// Create a new request using http
req, err := http.NewRequest("GET", url, nil)
// add authorization header to the req
req.Header.Add("Authorization", bearer)
//This is what the response from the API looks like
//regionJson := `[{"region":"GEO:ABC","Description":"ABCLand","Id":1,"Name":"ABCLand [GEO-ABC]","Status":1,"Nodes":[{"NodeId":17,"Code":"LAX","Continent":"North America","City":"Los Angeles"},{"NodeId":18,"Code":"LBC","Continent":"North America","City":"Long Beach"}]},{"region":"GEO:DEF","Description":"DEFLand","Id":2,"Name":"DEFLand","Status":1,"Nodes":[{"NodeId":15,"Code":"NRT","Continent":"Asia","City":"Narita"},{"NodeId":31,"Code":"TYO","Continent":"Asia","City":"Tokyo"}]}]`
//Send req using http Client
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Println("Error on response.\n[ERROR] -", err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Println("Error while reading the response bytes:", err)
}
var regions []Region
json.Unmarshal([]byte(body), &regions)
fmt.Printf("Regions: %+v", regions)
}

答案1

得分: 1

请看这个示例的游乐场 example,以获取一些指导。

以下是代码:

package main

import (
	"encoding/json"
	"log"
)

func main() {
	b := []byte(`
[
  {"key": "value", "key2": "value2"},
  {"key": "value", "key2": "value2"}
]`)

	var mm []map[string]string
	if err := json.Unmarshal(b, &mm); err != nil {
		log.Fatal(err)
	}

	for _, m := range mm {
		for k, v := range m {
			log.Printf("%s [%s]", k, v)
		}
	}
}

我重新格式化了你提供的 API 响应,因为它不是有效的 JSON。

在 Go 中,需要定义类型以匹配 JSON 模式。

我不知道为什么 API 在结果的末尾添加了 %,所以我忽略了它。如果包含了它,你需要在解组前修剪文件中的结果。

解组后得到的是一个映射的切片。然后,你可以迭代切片以获取每个映射,然后迭代每个映射以提取键和值。

更新

在你更新的问题中,你包含了一个不同的 JSON 模式,这个变化必须在 Go 代码中反映出来,通过更新类型。你的代码中还有一些其他错误。根据我的评论,我鼓励你花一些时间学习这门语言。

package main

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"log"
)

// Response 是表示 API 响应的类型
type Response []Record

// Record 是表示单个记录的类型
// 名称 Record 是任意的,因为在响应中它是无名的
// Golang 支持结构标签来映射 JSON 属性
// 例如,JSON "region" 映射到 Golang 字段 "Region"
type Record struct {
	Region      string `json:"region"`
	Description string `json:"description"`
	ID          int    `json:"id"`
	Nodes       []Node
}
type Node struct {
	NodeID int    `json:"NodeId"`
	Code   string `json:"Code"`
}

func main() {
	// 表示你的示例响应的字节切片
	b := []byte(`[{
		"region": "GEO:ABC",
		"Description": "ABCLand",
		"Id": 1,
		"Name": "ABCLand [GEO-ABC]",
		"Status": 1,
		"Nodes": [{
			"NodeId": 17,
			"Code": "LAX",
			"Continent": "North America",
			"City": "Los Angeles"
		}, {
			"NodeId": 18,
			"Code": "LBC",
			"Continent": "North America",
			"City": "Long Beach"
		}]
	}, {
		"region": "GEO:DEF",
		"Description": "DEFLand",
		"Id": 2,
		"Name": "DEFLand",
		"Status": 1,
		"Nodes": [{
			"NodeId": 15,
			"Code": "NRT",
			"Continent": "Asia",
			"City": "Narita"
		}, {
			"NodeId": 31,
			"Code": "TYO",
			"Continent": "Asia",
			"City": "Tokyo"
		}]
	}]`)

	// 为了更接近你的代码,创建一个 Reader
	rdr := bytes.NewReader(b)

	// 这与你的代码匹配,从 Reader 中读取
	body, err := ioutil.ReadAll(rdr)
	if err != nil {
		// 使用 Printf 格式化字符串
		log.Printf("读取响应字节时出错\n%s", err)
	}

	// 初始化一个 Response 类型的变量
	resp := &Response{}
	// 尝试将 body 解组到它中
	if err := json.Unmarshal(body, resp); err != nil {
		log.Fatal(err)
	}

	// 打印结果
	log.Printf("%+v", resp)
}
英文:

Have a look at this playground example for some pointers.

Here's the code:

package main

import (
	"encoding/json"
	"log"
)

func main() {
	b := []byte(`
[
  {"key": "value", "key2": "value2"},
  {"key": "value", "key2": "value2"}
]`)

	var mm []map[string]string
	if err := json.Unmarshal(b, &mm); err != nil {
		log.Fatal(err)
	}

	for _, m := range mm {
		for k, v := range m {
			log.Printf("%s [%s]", k, v)
		}
	}
}

I reformatted the API response you included because it is not valid JSON.

In Go it's necessary to define types to match the JSON schema.

> I don't know why the API appends % to the end of the result so I've ignored that. If it is included, you will need to trim the results from the file before unmarshaling.

What you get from the unmarshaling is a slice of maps. Then, you can iterate over the slice to get each map and then iterate over each map to extract the keys and values.

Update

In your updated question, you include a different JSON schema and this change must be reflect in the Go code by update the types. There are some other errors in your code. Per my comment, I encourage you to spend some time learning the language.

package main

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"log"
)

// Response is a type that represents the API response
type Response []Record

// Record is a type that represents the individual records
// The name Record is arbitrary as it is unnamed in the response
// Golang supports struct tags to map the JSON properties
// e.g. JSON "region" maps to a Golang field "Region"
type Record struct {
	Region      string `json:"region"`
	Description string `json:"description"`
	ID          int    `json:"id"`
	Nodes       []Node
}
type Node struct {
	NodeID int    `json:"NodeId`
	Code   string `json:"Code"`
}

func main() {
    // A slice of byte representing your example response
	b := []byte(`[{
		"region": "GEO:ABC",
		"Description": "ABCLand",
		"Id": 1,
		"Name": "ABCLand [GEO-ABC]",
		"Status": 1,
		"Nodes": [{
			"NodeId": 17,
			"Code": "LAX",
			"Continent": "North America",
			"City": "Los Angeles"
		}, {
			"NodeId": 18,
			"Code": "LBC",
			"Continent": "North America",
			"City": "Long Beach"
		}]
	}, {
		"region": "GEO:DEF",
		"Description": "DEFLand",
		"Id": 2,
		"Name": "DEFLand",
		"Status": 1,
		"Nodes": [{
			"NodeId": 15,
			"Code": "NRT",
			"Continent": "Asia",
			"City": "Narita"
		}, {
			"NodeId": 31,
			"Code": "TYO",
			"Continent": "Asia",
			"City": "Tokyo"
		}]
	}]`)

    // To more closely match your code, create a Reader
	rdr := bytes.NewReader(b)

    // This matches your code, read from the Reader
	body, err := ioutil.ReadAll(rdr)
	if err != nil {
        // Use Printf to format strings
		log.Printf("Error while reading the response bytes\n%s", err)
	}

    // Initialize a variable of type Response
	resp := &Response{}
    // Try unmarshaling the body into it
	if err := json.Unmarshal(body, resp); err != nil {
		log.Fatal(err)
	}

    // Print the result
	log.Printf("%+v", resp)
}

huangapple
  • 本文由 发表于 2022年2月17日 11:45:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/71152266.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定