猿问

使用 PostgreSQL 和 json-api 的发布请求返回一个空体

在 POST 请求之后,我期望将最后插入的记录编组到 json 中,但返回一个空体。我做的不好吗?


package models



import (

    "encoding/json"

    "errors"

    "flag"

    "fmt"

    "log"

    "net/http"

    "strconv"


    "github.com/go-chi/chi"

    "github.com/google/jsonapi"

    "github.com/thedevsaddam/renderer"

    "github.com/xo/dburl"

)


var rnd = renderer.New()


var flagVerbose = flag.Bool("v", false, "verbose")


var FlagURL = flag.String("url", "postgres://postgres:@127.0.0.1/sweb", "url")


// Page represents a row from 'public.pages'.

type Page struct {

    Tag   string `jsonapi:"attr,tag"`      // tag

    Body  string `jsonapi:"attr,body"`     // body

    Slug  string `jsonapi:"attr,slug"`     // slug

    Title string `jsonapi:"attr,title"`    // title

    ID    int    `jsonapi:"primary,pages"` // id

    Link  string `jsonapi:"attr,link"`     // link


    // xo fields

    _exists, _deleted bool

}


func (page Page) JSONAPILinks() *jsonapi.Links {

    return &jsonapi.Links{

        "self": fmt.Sprintf("https://%d", page.ID),

    }

}

我相信这是罪魁祸首。插入记录后,它应该返回指定的最后插入的记录。


func (p *Page) PInsert(db XODB) (*Page, error) {

    var err error


    // if already exist, bail

    if p._exists {

        return p, errors.New("insert failed: already exists")

    }


    // sql insert query, primary key provided by sequence

    const sqlstr = `INSERT INTO public.pages (` +

        `tag, body, slug, title` +

        `) VALUES (` +

        `$1, $2, $3, $4` +

        `) RETURNING id, tag, body, title`


    // run query

    XOLog(sqlstr, p.Tag, p.Body, p.Slug, p.Title)

    err = db.QueryRow(sqlstr, p.Tag, p.Body, p.Slug, p.Title).Scan(&p.ID, &p.Tag, &p.Body, &p.Title)

    if err != nil {

        return p, err

    }


    // set existence

    p._exists = true


    return p, nil

}

更新更新数据库中的页面并返回最后插入的记录。这同样适用于更新功能

这是我认为问题发生的最后一个功能。最后插入的记录应该编组到 json 中。



莫回无
浏览 96回答 1
1回答

www说

您的最后一段代码包含许多错误。相关部分(没有无用和混淆的 Printlns)是:p, err := page.PSave(db)if err != nil {    if err := jsonapi.MarshalPayload(w, p); err != nil {        http.Error(w, err.Error(), http.StatusInternalServerError)    }}w.Header().Set("Content-Type", jsonapi.MediaType)w.WriteHeader(http.StatusCreated)主要的错误是json.MarshalPayload它只在err != nil. 换句话说,只有在保存失败时才序列化该页面。第二个错误是jsonapi.MarshalPayload将Write调用http.ResponseWriter. 这会将所有后续调用 Header().Set变成WriteHeader空操作。更正确的代码看起来像这样。// 1. Save the page in the database, bail on errorp, err := page.PSave(db)if err != nil {    http.Error(w, err.Error(), http.StatusInternalServerError)    return }// 2. Marshal the page into an intermediate buffer, bail on errorvar buf bytes.Bufferif err := jsonapi.MarshalPayload(&buf, p); err != nil {    http.Error(w, err.Error(), http.StatusInternalServerError)    return }// 3. Write the entire response; failures to write the intermediate buffer// cannot be communicated over HTTPw.Header().Set("Content-Type", jsonapi.MediaType)w.WriteHeader(http.StatusCreated)if _, err := buf.WriteTo(w); err != nil {    log.Printf("failed to write response: %v", err)    return }
随时随地看视频慕课网APP

相关分类

Go
我要回答