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

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

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

没有必要将bodyHttpResp分开进行编排。相反,将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})
}

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:

确定