将Golang中的JSON API调用响应输出到Next.js前端。

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

Outputting a JSON API call response from Golang to a nextjs frontend

问题

我得到的错误是:

错误:在“/”中从“getServerSideProps”返回的“.username”的序列化错误。
原因:无法将“undefined”序列化为JSON。请使用“null”或省略此值。

我的后端Go代码正常工作,我可以在Postman上检查它,但是我无法从后端获取API响应以弹出任何反馈或代码改进都是可以的
:Main.go

package main

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

func main() {
	handler := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
		var resp []byte
		if req.URL.Path == "/status" {
			resp = []byte(`{"status": "ok"}`)
		} else if req.URL.Path == "/username" {
			resp = []byte(GetData())
			json.NewEncoder(rw).Encode(resp)
		} else {
			rw.WriteHeader(http.StatusNotFound)
			return
		}
		
		rw.Header().Set("Content-Type", "application/json")
		rw.Header().Set("Content-Length", fmt.Sprint(len(resp)))
		rw.Write(resp)
	})

	log.Println("Server is available at http://localhost:8000")
	log.Fatal(http.ListenAndServe(":8000", handler))
}

:data.go - 此文件用作API的酷JSON响应

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "os"
)

func GetData( ) string {
    response, err := http.Get("http://pokeapi.co/api/v2/pokedex/kanto/")

    if err != nil {
        fmt.Print(err.Error())
        os.Exit(1)
    }

    responseData, err := ioutil.ReadAll(response.Body)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(string(responseData))
return ""
}

index.ts是我用于前端的Next.js文件

export async function getServerSideProps() {
  const {status} = await fetch("http://localhost:8000/status").then(x => x.json());
  const {username} = await fetch("http://localhost:8000/username").then(x => x.json());
  let res = await {username: JSON, status: JSON}; 
  console.log("res: ", res);
  return {
    props: {
      status: status,
      username: username,
    }
  }
}

export default function Home({status, username}: {status: any, username: any}) {
  return (
    <div className="">
      <main className="">
        <h1 className="">
          Welcome to <a href="https://nextjs.org">Next.js!</a>
        </h1>
        <div>Status is: {status}, your username is: {username}</div>
      </main>
    </div>
  )
}
英文:

The Error I am getting is

Error: Error serializing `.username` returned from `getServerSideProps` in &quot;/&quot;.
Reason: `undefined` cannot be serialized as JSON. Please use `null` or omit this value.

My backend go is working fine I can check it on postman however I can not get the API response from my backend to pop up any feedback or code improvments are welcome
:Main.go

package main

import (
	&quot;encoding/json&quot;
	&quot;fmt&quot;
	&quot;log&quot;
	&quot;net/http&quot;
)

func main() {
	handler := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
		var resp []byte
		if req.URL.Path == &quot;/status&quot; {
			resp = []byte(`{&quot;status&quot;: &quot;ok&quot;}`)
		} else if req.URL.Path == &quot;/username&quot; {
			resp = []byte(GetData())
			json.NewEncoder(rw).Encode(resp)
		} else {
			rw.WriteHeader(http.StatusNotFound)
			return
		}
		
		rw.Header().Set(&quot;Content-Type&quot;, &quot;application/json&quot;)
		rw.Header().Set(&quot;Content-Length&quot;, fmt.Sprint(len(resp)))
		rw.Write(resp)
	})

	log.Println(&quot;Server is available at http://localhost:8000&quot;)
	log.Fatal(http.ListenAndServe(&quot;:8000&quot;, handler))
}

: data.go - This file serves as api cool json response

package main

import (
    &quot;fmt&quot;
    &quot;io/ioutil&quot;
    &quot;log&quot;
    &quot;net/http&quot;
    &quot;os&quot;
)

func GetData( ) string {
    response, err := http.Get(&quot;http://pokeapi.co/api/v2/pokedex/kanto/&quot;)

    if err != nil {
        fmt.Print(err.Error())
        os.Exit(1)
    }

    responseData, err := ioutil.ReadAll(response.Body)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(string(responseData))
return &quot;&quot;
}

index.ts nextjs file that I am using for frontend

export async function getServerSideProps() {
  const {status} = await fetch(&quot;http://localhost:8000/status&quot;).then(x =&gt; x.json());
  const {username} = await fetch(&quot;http://localhost:8000/username&quot;).then(x =&gt; x.json());
  let res = await {username: JSON, status: JSON}; 
  console.log(&quot;res: &quot;, res);
  return {
    props: {
      status: status,
      username: username,
    }
  }
}

export default function Home({status, username}: {status: any, username: any}) {
  return (
    &lt;div className=&quot;&quot;&gt;


      &lt;main className=&quot;&quot;&gt;
        &lt;h1 className=&quot;&quot;&gt;
          Welcome to &lt;a href=&quot;https://nextjs.org&quot;&gt;Next.js!&lt;/a&gt;
        &lt;/h1&gt;
        &lt;div&gt;Status is: {status}, your username is: {username}&lt;/div&gt;
      &lt;/main&gt;
    &lt;/div&gt;
  )
}

答案1

得分: 1

GetData()目前返回一个&quot;&quot;

你可以更新GetData函数,使其返回[]byte类型:

func GetData() ([]byte, error) {
	response, err := http.Get("http://pokeapi.co/api/v2/pokedex/kanto/")
	if err != nil {
		return nil, err
	}

	responseData, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	return responseData, nil
}

然后,你可以将/username分支更新如下:

} else if req.URL.Path == "/username" {
	data, err := GetData()
	if err != nil {
		http.Error(rw, err.Error(), http.StatusInternalServerError)
		return
	}
	resp = data
} 

你的数据已经是JSON的字节,所以你不需要使用json.NewEncoder().Encode,你可以直接重新赋值resp并将这些字节直接写入。

如果你确实需要写入JSON,你不能在写入头部之前向响应写入内容,所以如果你需要在写入响应体时进行更复杂的操作,你可能需要调整一下代码中的顺序。

英文:

GetData() currently returns a &quot;&quot;

You could update GetData to return []byte:

func GetData() ([]byte, error) {
	response, err := http.Get(&quot;http://pokeapi.co/api/v2/pokedex/kanto/&quot;)
	if err != nil {
		return nil, err
	}

	responseData, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	return responseData, nil
}

You can then update the /username branch to be as follows:

} else if req.URL.Path == &quot;/username&quot; {
	data, err := GetData()
	if err != nil {
		http.Error(rw, err.Error(), http.StatusInternalServerError)
		return
	}
	resp = data
} 

Your data is already bytes of json, so you do not need json.NewEncoder().Encode, you can just re-assign the resp value you have and write those bytes directly.

If you did need to do write json you can't write to the response-writer before writing headers, so you might need to move those around if you end up doing more complicated things with writing response bodies.

答案2

得分: 1

你的GetData()函数只返回了一个空字符串。

你可能应该创建一个结构体来解析JSON,并返回解析后的结构体。或者你可以直接传递字节。

英文:

Your GetData() function just returns ""

You should probably create a struct to unmarshal the json into and then return that marshaled. Or you could just pass on the bytes.

huangapple
  • 本文由 发表于 2023年2月25日 08:08:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/75562457.html
匿名

发表评论

匿名网友

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

确定