【问题标题】:Wrong JSON is returned返回错误的 JSON
【发布时间】:2023-01-24 23:24:18
【问题描述】:

我有下面的代码,假设返回一个 JSON 作为:

{
    "ID": "1",
    "Name": "bob"
}

但实际上它缺少项目周围的",我得到:

{
    ID: "1",
    Name: "bob"
}

这不是在以下位置检查的有效 JSON:https://jsonlint.com/

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
    "reflect"
    "regexp"
    "strings"
    "sync"
)

var (
    getUserRe    = regexp.MustCompile(`^\/users\/(\d+)$`)
)

type user struct {
    ID   string `json:"id"`
    Name string `json:"name"`
}

type response struct {
    MsgType    string `json:"type"`
    MsgDeatial string `json:"details"`
}

type datastore struct {
    m map[string]user
    *sync.RWMutex
}

type userHandler struct {
    store *datastore
}

func (h *userHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("content-type", "application/json")
    switch {
    case r.Method == http.MethodGet && getUserRe.MatchString(r.URL.Path):
        h.Get(w, r)
        return
    default:
        notFound(w, r)
        return
    }
}

func (h *userHandler) List(w http.ResponseWriter, r *http.Request) {
    h.store.RLock()
    users := make([]user, 0, len(h.store.m))
    for _, v := range h.store.m {
        users = append(users, v)
    }
    h.store.RUnlock()
    jsonBytes, err := json.Marshal(users)
    if err != nil {
        internalServerError(w, r)
        return
    }
    w.WriteHeader(http.StatusOK)
    w.Write(jsonBytes)
}

func (h *userHandler) Get(w http.ResponseWriter, r *http.Request) {
    matches := getUserRe.FindStringSubmatch(r.URL.Path)
    if len(matches) < 2 {
        notFound(w, r)
        return
    }
    h.store.RLock()
    u, ok := h.store.m[matches[1]]
    h.store.RUnlock()
    if !ok {
        w.WriteHeader(http.StatusNotFound)
        //w.Write([]byte("user not found"))
        myJsonString := response{
            MsgType:    "Error",
            MsgDeatial: "user not found",
        }
        jsonBytes, err := json.Marshal(myJsonString)
        if err != nil {
            internalServerError(w, r)
            return
        }
        w.Write(jsonBytes)
        return
    }
    /*  jsonBytes, err := json.Marshal(u)
        if err != nil {
            internalServerError(w, r)
            return
        } */
    w.WriteHeader(http.StatusOK)
    //w.Write(jsonBytes)
    //x := fmt.Sprintf("%#v\n", u) // => main.user{ID:"1", Name:"bob"} // include the field names, and the struct type
    //x := fmt.Sprintf("%+v\n", u) // => {ID:1 Name:bob} // include the field names, but not the struct type
    //x := fmt.Sprintf("%v\n", u) // => {1 bob}

    x := fmt.Sprintf("%v", strings.Trim(fmt.Sprintf("%#v", u), fmt.Sprintf("%+v", reflect.TypeOf(u))))
    println(x)
    myJsonString := response{
        MsgType:    "Success",
        MsgDeatial: x,
    }
    jsonBytes, err := json.Marshal(myJsonString)
    if err != nil {
        internalServerError(w, r)
        return
    }
    w.Write(jsonBytes)
}

func internalServerError(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(http.StatusInternalServerError)
    w.Write([]byte("internal server error"))
}

func notFound(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(http.StatusNotFound)
    w.Write([]byte("not found"))
}

func main() {
    mux := http.NewServeMux()
    userH := &userHandler{
        store: &datastore{
            m: map[string]user{
                "1": {ID: "1", Name: "bob"},
            },
            RWMutex: &sync.RWMutex{},
        },
    }
    mux.Handle("/users", userH)
    mux.Handle("/users/", userH)

    http.ListenAndServe("localhost:80", mux)
}

【问题讨论】:

  • x := fmt.Sprintf("%v", strings.Trim(fmt.Sprintf("%#v", u), fmt.Sprintf("%+v", reflect.TypeOf(u)))) <- 这不是您生成 JSON 的方式。您甚至试图通过该声明实现什么目标?
  • 无论如何,当您要调用 MarshalJSON 时,为什么要尝试将 json 手动写入结构?输出不是有效的 json,因为你没有写有效的 json。不要尝试使用 fmt.Sprintf 编写 json。

标签: go


【解决方案1】:

让 JSON 包进行编码,而不是您自己生成字符串。

声明响应具有任何类型的 MsgDeatial:

type response struct {
    MsgType    string `json:"type"`
    MsgDeatial any `json:"details"`
}

删除 sprintf 代码。将 MsgDeatial 设置为用户和编组:

myJsonString := response{
    MsgType:    "Success",
    MsgDeatial: u,
}
jsonBytes, err := json.Marshal(myJsonString)

变量 jsonBytes 将包含 u 的正确 JSON。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-20
    • 1970-01-01
    • 1970-01-01
    • 2014-11-15
    • 1970-01-01
    • 1970-01-01
    • 2020-06-30
    • 1970-01-01
    相关资源
    最近更新 更多