英文:
Is there a way to format this json in golang?
问题
我刚开始学习Go语言,我正在尝试构建一个简单的Rest API Web服务器。
这是我想要发送给Web服务器的每个请求的响应结构体:
package main
type HttpResp struct{
Status int `json:"status"`
Description string `json:"description"`
Body interface{} `json:"body"`
}
这是我的articles.go文件,其中包含从数据库中获取所有文章的函数:
package main
import (
"encoding/json"
"net/http"
"log"
)
type Article struct{
Id string `json:"id"`
Title string `json:"title"`
Body string `json:"body"`
Description string `json:"description"`
}
func AllArticles(w http.ResponseWriter, r *http.Request){
log.Print("/articles - GET")
db := connect()
defer db.Close()
var articles []Article
results, err := db.Query("SELECT * FROM Articles")
if err != nil{
log.Print(err)
return
}
for results.Next(){
var article Article
err = results.Scan(&article.Title, &article.Description, &article.Body, &article.Id)
if err != nil{
serr, _ := json.Marshal(err)
json.NewEncoder(w).Encode(HttpResp{Status: 500, Description: "Failed to retrieve all articles", Body: string(serr)})
}
articles = append(articles, article)
}
sarr, _ := json.Marshal(articles)
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(HttpResp{Status: 200, Body: json.RawMessage(sarr)})
}
我在这里遇到的问题是响应的格式如下:
{"status":200,"description":"","body":"[{\"id\":\"1\",\"title\":\"First\",\"body\":\"This is a test body\",\"description\":\"This is a test\"}]"}
我希望body只是一个JSON而不是一个字符串。我该如何实现这一点?
英文:
I'm just starting to learn GoLang today, I'm trying to build a simple Rest API Web server.
Here's the response Struct I want to send for each request to the web server :
package main
type HttpResp struct{
Status int `json:"status"`
Description string `json:"description"`
Body string `json:"body"`
}
And here's my articles.go file who have the function who gets all the articles in the database :
package main
import (
"encoding/json"
"net/http"
"log"
)
type Article struct{
Id string `json:"id"`
Title string `json:"title"`
Body string `json:"body"`
Description string `json:"description"`
}
func AllArticles(w http.ResponseWriter, r *http.Request){
log.Print("/articles - GET")
db := connect()
defer db.Close()
var articles []Article
results, err := db.Query("SELECT * FROM Articles")
if err != nil{
log.Print(err)
return
}
for results.Next(){
var article Article
err = results.Scan(&article.Title, &article.Description, &article.Body, &article.Id)
if err != nil{
serr, _ := json.Marshal(err)
json.NewEncoder(w).Encode(HttpResp{Status: 500, Description: "Failed to retrieve all articles", Body: string(serr)})
}
articles = append(articles, article)
}
sarr, _ := json.Marshal(articles)
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(HttpResp{Status: 200, Body: string(sarr)})
}
The issue I'm facing here is that the response is like this :
> {"status":200,"description":"","body":"[{"id":"1","title":"First","body":"This
> is a test body","description":"This is a test"}]"}
I'd like the body to be just JSON and not a string. How can I acheive that ?
答案1
得分: 2
没有必要将body
与HttpResp
分开进行编排。相反,将Body
字段的类型更改为interface{}
,然后将该字段设置为具体类型的任何值,而不是JSON字符串,例如[]Article
,然后一次编排响应。
type HttpResp struct{
Status int `json:"status"`
Description string `json:"description"`
Body interface{} `json:"body"`
}
And the rest...
package main
import (
"encoding/json"
"net/http"
"log"
)
type Article struct{
Id string `json:"id"`
Title string `json:"title"`
Body string `json:"body"`
Description string `json:"description"`
}
func AllArticles(w http.ResponseWriter, r *http.Request){
log.Print("/articles - GET")
db := connect()
defer db.Close()
var articles []Article
results, err := db.Query("SELECT * FROM Articles")
if err != nil{
log.Print(err)
return
}
for results.Next(){
var article Article
err = results.Scan(&article.Title, &article.Description, &article.Body, &article.Id)
if err != nil{
serr, _ := json.Marshal(err)
json.NewEncoder(w).Encode(HttpResp{Status: 500, Description: "Failed to retrieve all articles", Body: string(serr)})
}
articles = append(articles, article)
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(HttpResp{Status: 200, Body: articles})
}
英文:
No point in marshalling the body separately from the HttpResp
. Instead change the Body
field's type to interface{}
and then set the field to any value of a concrete type as opposed to a json string, e.g. []Article
and then marshal the resp once.
type HttpResp struct{
Status int `json:"status"`
Description string `json:"description"`
Body interface{} `json:"body"`
}
And the rest...
package main
import (
"encoding/json"
"net/http"
"log"
)
type Article struct{
Id string `json:"id"`
Title string `json:"title"`
Body string `json:"body"`
Description string `json:"description"`
}
func AllArticles(w http.ResponseWriter, r *http.Request){
log.Print("/articles - GET")
db := connect()
defer db.Close()
var articles []Article
results, err := db.Query("SELECT * FROM Articles")
if err != nil{
log.Print(err)
return
}
for results.Next(){
var article Article
err = results.Scan(&article.Title, &article.Description, &article.Body, &article.Id)
if err != nil{
serr, _ := json.Marshal(err)
json.NewEncoder(w).Encode(HttpResp{Status: 500, Description: "Failed to retrieve all articles", Body: string(serr)})
}
articles = append(articles, article)
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(HttpResp{Status: 200, Body: articles})
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论