有没有一种方法可以在Golang中格式化这个JSON?

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

Is there a way to format this json in golang?

问题

我刚开始学习Go语言,我正在尝试构建一个简单的Rest API Web服务器。

这是我想要发送给Web服务器的每个请求的响应结构体:

  1. package main
  2. type HttpResp struct{
  3. Status int `json:"status"`
  4. Description string `json:"description"`
  5. Body interface{} `json:"body"`
  6. }

这是我的articles.go文件,其中包含从数据库中获取所有文章的函数:

  1. package main
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "log"
  6. )
  7. type Article struct{
  8. Id string `json:"id"`
  9. Title string `json:"title"`
  10. Body string `json:"body"`
  11. Description string `json:"description"`
  12. }
  13. func AllArticles(w http.ResponseWriter, r *http.Request){
  14. log.Print("/articles - GET")
  15. db := connect()
  16. defer db.Close()
  17. var articles []Article
  18. results, err := db.Query("SELECT * FROM Articles")
  19. if err != nil{
  20. log.Print(err)
  21. return
  22. }
  23. for results.Next(){
  24. var article Article
  25. err = results.Scan(&article.Title, &article.Description, &article.Body, &article.Id)
  26. if err != nil{
  27. serr, _ := json.Marshal(err)
  28. json.NewEncoder(w).Encode(HttpResp{Status: 500, Description: "Failed to retrieve all articles", Body: string(serr)})
  29. }
  30. articles = append(articles, article)
  31. }
  32. sarr, _ := json.Marshal(articles)
  33. w.Header().Set("Content-Type", "application/json")
  34. json.NewEncoder(w).Encode(HttpResp{Status: 200, Body: json.RawMessage(sarr)})
  35. }

我在这里遇到的问题是响应的格式如下:

  1. {"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 :

  1. package main
  2. type HttpResp struct{
  3. Status int `json:"status"`
  4. Description string `json:"description"`
  5. Body string `json:"body"`
  6. }

And here's my articles.go file who have the function who gets all the articles in the database :

  1. package main
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "log"
  6. )
  7. type Article struct{
  8. Id string `json:"id"`
  9. Title string `json:"title"`
  10. Body string `json:"body"`
  11. Description string `json:"description"`
  12. }
  13. func AllArticles(w http.ResponseWriter, r *http.Request){
  14. log.Print("/articles - GET")
  15. db := connect()
  16. defer db.Close()
  17. var articles []Article
  18. results, err := db.Query("SELECT * FROM Articles")
  19. if err != nil{
  20. log.Print(err)
  21. return
  22. }
  23. for results.Next(){
  24. var article Article
  25. err = results.Scan(&article.Title, &article.Description, &article.Body, &article.Id)
  26. if err != nil{
  27. serr, _ := json.Marshal(err)
  28. json.NewEncoder(w).Encode(HttpResp{Status: 500, Description: "Failed to retrieve all articles", Body: string(serr)})
  29. }
  30. articles = append(articles, article)
  31. }
  32. sarr, _ := json.Marshal(articles)
  33. w.Header().Set("Content-Type", "application/json")
  34. json.NewEncoder(w).Encode(HttpResp{Status: 200, Body: string(sarr)})
  35. }

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

没有必要将bodyHttpResp分开进行编排。相反,将Body字段的类型更改为interface{},然后将该字段设置为具体类型的任何值,而不是JSON字符串,例如[]Article,然后一次编排响应。

  1. type HttpResp struct{
  2. Status int `json:"status"`
  3. Description string `json:"description"`
  4. Body interface{} `json:"body"`
  5. }
  6. And the rest...
  7. package main
  8. import (
  9. "encoding/json"
  10. "net/http"
  11. "log"
  12. )
  13. type Article struct{
  14. Id string `json:"id"`
  15. Title string `json:"title"`
  16. Body string `json:"body"`
  17. Description string `json:"description"`
  18. }
  19. func AllArticles(w http.ResponseWriter, r *http.Request){
  20. log.Print("/articles - GET")
  21. db := connect()
  22. defer db.Close()
  23. var articles []Article
  24. results, err := db.Query("SELECT * FROM Articles")
  25. if err != nil{
  26. log.Print(err)
  27. return
  28. }
  29. for results.Next(){
  30. var article Article
  31. err = results.Scan(&article.Title, &article.Description, &article.Body, &article.Id)
  32. if err != nil{
  33. serr, _ := json.Marshal(err)
  34. json.NewEncoder(w).Encode(HttpResp{Status: 500, Description: "Failed to retrieve all articles", Body: string(serr)})
  35. }
  36. articles = append(articles, article)
  37. }
  38. w.Header().Set("Content-Type", "application/json")
  39. json.NewEncoder(w).Encode(HttpResp{Status: 200, Body: articles})
  40. }
英文:

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.

  1. type HttpResp struct{
  2. Status int `json:"status"`
  3. Description string `json:"description"`
  4. Body interface{} `json:"body"`
  5. }

And the rest...

  1. package main
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "log"
  6. )
  7. type Article struct{
  8. Id string `json:"id"`
  9. Title string `json:"title"`
  10. Body string `json:"body"`
  11. Description string `json:"description"`
  12. }
  13. func AllArticles(w http.ResponseWriter, r *http.Request){
  14. log.Print("/articles - GET")
  15. db := connect()
  16. defer db.Close()
  17. var articles []Article
  18. results, err := db.Query("SELECT * FROM Articles")
  19. if err != nil{
  20. log.Print(err)
  21. return
  22. }
  23. for results.Next(){
  24. var article Article
  25. err = results.Scan(&article.Title, &article.Description, &article.Body, &article.Id)
  26. if err != nil{
  27. serr, _ := json.Marshal(err)
  28. json.NewEncoder(w).Encode(HttpResp{Status: 500, Description: "Failed to retrieve all articles", Body: string(serr)})
  29. }
  30. articles = append(articles, article)
  31. }
  32. w.Header().Set("Content-Type", "application/json")
  33. json.NewEncoder(w).Encode(HttpResp{Status: 200, Body: articles})
  34. }

huangapple
  • 本文由 发表于 2017年8月26日 05:08:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/45889437.html
匿名

发表评论

匿名网友

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

确定