go

json: cannot unmarshal object into Go value of type jsonpatch.Patch - How to Fix


import (
    "database/sql"
    "encoding/json"
    "fmt"
    "io"
    "net/http"

    jsonpatch "github.com/evanphx/json-patch"
    "github.com/gin-gonic/gin"
    "github.com/jasonalansmith/maelstrom-platform-api/database"
)

type Issue struct {
    SysId        uint   `json:"sysid,omitempty"`
    Identifier   string `json:"identifier,omitempty"`
    SummaryBrief string `json:"summarybrief,omitempty"`
    SummaryLong  string `json:"summarylong,omitempty"`
}

func patchIssue(ctx *gin.Context) {
    id := ctx.Param("sysid")

    //  body := Issue{}
    //data, err := ctx.GetRawData()
    //if err != nil {
    //  ctx.AbortWithStatusJSON(400, "Issue not defined.")
    //  return
    //}
    //err = json.Unmarshal(data, &body)
    //if err != nil {
    //  fmt.Println(err)
    //  ctx.AbortWithStatusJSON(400, "Bad input.")
    //  return
    //}

    iss := Issue{}
    sqls := "SELECT * FROM issue WHERE sysid = $1"
    res := database.Db.QueryRow(sqls, id)
    err := res.Scan(&iss.SysId, &iss.Identifier, &iss.SummaryBrief,
        &iss.SummaryLong)
    if err == sql.ErrNoRows {
        ctx.AbortWithStatusJSON(400, "Issue does not exist.")
        return
    }

    issueBytes, err := json.Marshal(iss)
    if err != nil {
        fmt.Println("Error creating patch json ", err.Error())
        return
    }

    patchJSON, err := io.ReadAll(ctx.Request.Body)
    fmt.Println(string(patchJSON))
    if err != nil {
        fmt.Println(err)
    }

    patch, err := jsonpatch.DecodePatch(patchJSON)
    if err != nil {
        fmt.Println("Error decoding patch json ", err.Error())
        return
    }

    patchedIssue, err := patch.Apply(issueBytes)
    if err != nil {
        fmt.Println("Error applying patch json ", err.Error())
        return
    }

    fmt.Println(patchedIssue)
}

Using Go version:

go version go1.21.1 linux/amd64

When I run this code, I get the following error:

json: cannot unmarshal object into Go value of type jsonpatch.Patch

I've adapted this code from here.

When I do:

fmt.Println(string(patchJSON))

I get what looks like valid JSON.

The offending line is:

patch, err := jsonpatch.DecodePatch(patchJSON)

I'm using curl on openSuse Tumbleweed to make the API call:

curl -d '{"op": "replace", "path": "/summarybrief", "value": "Second Test Issue"}' -X PATCH http://localhost:8080/issue/22 -H "Content-Type: application/json"

What am I doing wrong to get this error? Thanks!


Solution

  • {"op": "replace", "path": "/summarybrief", "value": "Second Test Issue"} is not a valid patch. As per the spec:

    A JSON Patch document is a JSON [RFC4627] document that represents an array of objects.

    So the patch needs to be an array - e.g. [{"op": "replace", "path": "/summarybrief", "value": "Second Test Issue"}] would work as per the following example (playground):

    package main
    
    import (
        "fmt"
    
        jsonpatch "github.com/evanphx/json-patch/v5"
    )
    
    func main() {
        //  patchJSON := []byte(`{"op": "replace", "path": "/summarybrief", "value": "Second Test Issue"}`) // Fails with "Error decoding patch json  json: cannot unmarshal object into Go value of type jsonpatch.Patch"
        patchJSON := []byte(`[{"op": "replace", "path": "/summarybrief", "value": "Second Test Issue"}]`) // Successfully processed
        patch, err := jsonpatch.DecodePatch(patchJSON)
        if err != nil {
            fmt.Println("Error decoding patch json ", err.Error())
            return
        }
        fmt.Println(patch)
    }