【问题标题】:how to find, "invalid character ',' looking for beginning of value" error message如何找到“无效字符','寻找值的开头”错误消息
【发布时间】:2021-07-16 20:46:36
【问题描述】:

我有一个简短的 Go 程序,它为多个包运行 go list -json 命令,将每次运行命令的输出存储在 json.RawMessage 中,将每个 json.RawMessage 附加到一段 json.RawMessages 中,然后将每个 json.RawMessages 连接在一起并压缩 json 后,将结果返回给服务器。但是,当我运行 json.Compact 时会产生一条错误消息,我无法找到它的来源。谷歌搜索这条错误消息表明,大多数遇到它的人——无论是无效的, 还是其他字符——都很难找到它的来源。

invalid character ',' looking for beginning of value

带有 cmets 的代码可以在这里查看on play.golang.org(虽然它不会在那里运行),也可以在下面查看。

问题:能否解释一下这个错误的来源以及如何预防?

(请注意,某些软件包仅用于测试目的)

package main

import (
    "expvar"

    "encoding/json"

    "bytes"
    "fmt"
    "github.com/go-martini/martini"
    "github.com/zenazn/goji"
    "github.com/zenazn/goji/web"
    "go/build"
    "log"
    "math/rand"
    "net/http"
    _ "net/http/pprof"
    "os/exec"
)

type myType struct {
    J []json.RawMessage
}

var pack map[string]string

type GoList struct {
    Imports []string
}

type Import struct {
    Dir        string
    ImportPath string
    Name       string
    Target     string
    Standard   bool
    Root       string
    GoFiles    []string
    Imports    []string
    Deps       []string
}

const contentTypeJSON = "application/json"

func main() {

    http.HandleFunc("/importgraph", func(w http.ResponseWriter, r *http.Request) { importGraph(w, r) })
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)

}

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Println("Inside handler")
    fmt.Fprintf(w, "Hello world from my Go program!")
}

func importGraph(w http.ResponseWriter, r *http.Request) {

    pack = make(map[string]string)

    var t myType
    cmd := exec.Command("go", "list", "-json")
    stdout, err := cmd.Output()
    if err != nil {

        println(err.Error())
        return
    }

    var list GoList
    err = json.Unmarshal(stdout, &list)

    for _, d := range list.Imports {
        //get the imports for each of the packages listed by go list -json
        t.imports(d)

    }

    var buff bytes.Buffer

    //concatenate the separate json.RawMessages together into json

    buff.WriteByte('[')

    for i, j := range t.J {

        if i != 0 {
            buff.WriteByte(',')
        }
        buff.Write([]byte(j))
    }
    buff.WriteByte(']')

    var buffer bytes.Buffer
    if err := json.Compact(&buffer, buff.Bytes()); err != nil {
        println(err.Error()) //error message: invalid character ',' looking for beginning of value
        return

    }

    w.Header().Set("Content-Type", contentTypeJSON)

    w.Write(buffer.Bytes())

}

func (myObj *myType) imports(pk string) error {

    cmd := exec.Command("go", "list", "-json", pk)
    stdout, _ := cmd.Output()

    pack[pk] = pk

    var deplist Import
    json.Unmarshal(stdout, &deplist)

    var newj json.RawMessage
    json.Unmarshal(stdout, &newj)
    myObj.J = append(myObj.J, newj)

    for _, imp := range deplist.Imports {

        if _, ok := pack[imp]; !ok {

            myObj.imports(imp) //recursive call to get the imports of the imports etc

        }
    }

    return nil

}

【问题讨论】:

  • 有关该错误的更多详细信息?行号/任何其他跟踪?
  • go list 命令是go/build 包的包装。我建议从您的应用程序中调用 build.DefaultContext.Import(path, "", 0) 来获取导入,而不是执行 go list 命令。
  • @Momer 它没有给出行号,也没有给出踪迹。有没有办法创建跟踪?
  • @thundercat 我想要 go list 命令的 json 输出。你能建议我如何将 go build 转为 json 吗?
  • 以下是如何将具有给定路径的包的导入编码为 JSON:p, err := build.DefaultContext.Import(path, "", 0); jsonBytes, err := json.Marshal(p.Imports) 一般策略是建立一个与您想要的 JSON 值相对应的 Go 值,然后调用 json.Marshal(五)。

标签: go


【解决方案1】:

首先,正如已评论的那样,您确定不能使用 go/build 包直接而不是运行 go list?

我不会在 HTTP 处理程序中使用 println(或 fmt.Println)。最好使用log.Println 和/或将错误写入ResponseWriter。此外,最好用log.Fatal 包裹您的ListenAndServe 呼叫。

当打印/记录error 值时,您可以使用err,不需要err.Error()

此外,当您实际上想要做一些比报告/记录错误消息更详细的事情时,您可以查看它的类型和其他信息。例如,log.Printf("verbose error info: %#v", err) 给出:

&json.SyntaxError{msg:"invalid character ',' looking for beginning of value", Offset:0}

我尝试了这个,因为我知道json 包返回各种错误类型以及附加信息,我希望偏移值会有所帮助。如果是这样,那么这样的事情可能会有所帮助:

if err := json.Compact(…) {
    if err != nil {
        log.Println("json.Compact:", err)
        if serr, ok := err.(*json.SyntaxError); ok {
            log.Println("Occurred at offset:", serr.Offset)
            // … something to show the data in buff around that offset …
        }
    }
}

但是零偏移没有帮助:(

因此,尽管这并不能确定您的问题,但希望如此 对您的进一步调查可能有所帮助。

编辑:

所以添加后:

log.Println("Write file:", ioutil.WriteFile("data.json", buff.Bytes(), 0600))

对于上面的错误处理块,然后我在结果文件上运行了一个 JSON 验证器,它识别出了这一部分:

        "XTestImports": [
                "io",
                "log",
                "net"
        ]
},,{
        "Dir": "/usr/local/go/src/mime",
        "ImportPath": "mime",
        "Name": "mime",

注意双重,,

这应该告诉您代码中的错误是什么。 但如果没有,您需要在处理t.J 或构建它时跳过空条目。后者更好,只涉及:

    if len(newj) > 0 {
        myObj.J = append(myObj.J, newj)
    }

(顺便说一句,您不检查来自 json.Unmarshal 的错误,因此不清楚它是否应该为空,或者是否由于先前的错误而为空。从不忽略错误返回!)

【讨论】:

  • 我想要 go list -json 的 json 输出,否则我必须手动构建 json,我不确定如何在 go 中执行此操作(这是我的第一个 go 项目)跨度>
  • @Leahcim 进一步调查了一窝垃圾并发现了问题。我将把剩下的答案留给你,因为它应该可以帮助你了解如何自己找到这些东西。
  • 这很有趣(你是如何发现问题的),但我不完全确定我理解它反对哪个字符。 Json.Compact 应该删除 \n 和 \t 字符,它们是问题吗?我会在我的电脑上试试你的鳕鱼
  • 好的,错误消失了,但现在我有一个新的类似类型的错误:数组元素后的无效字符'{''。你也明白了吗?
  • @Leahcim 首先检查您正在进行的每个json.* 调用的每个 错误返回,而不是像在imports 方法中那样忽略它们。
【解决方案2】:

我在 Go 程序中也遇到了相同的错误消息,但是当我的 HTTP 响应解析器需要 JSON 时,错误消息在 HTTP 响应错误中,采用 HTML 格式。

对我来说,解决方案是更改我的请求,将Content-Type 标头设置为application/json。你如何做到这一点取决于你碰巧使用的是哪个 http 客户端库;如果您可以访问http.Header 核心类型,则可以使用.Set(...) 设置标题。

我意识到此修复的范围可能不适用于原始问题,但我在谷歌搜索后首先来到这里并认为这对其他人有帮助,因为乍一看该消息并不是特别明显。提示是无效的<字符是错误/响应中的第一个HTML字符,这可能是请求类型未设置为application/json的结果,因此服务器以非JSON响应响应。

【讨论】:

    【解决方案3】:

    对我来说,问题是我试图解析已经解析的 JSON。

    【讨论】:

      【解决方案4】:

      我也遇到了这个错误“寻找值开头的无效字符'N'”。 在“将非 json 响应解组为 json”时出现此错误。我期待一个 json 响应,所以编写了 go 代码将其解组为 json。但是,由于 URL 更改,我得到的响应是文本,即。 “404 Not found”错误,无法解组为 json。 “寻找值开头的无效字符'N'”

      因此,总而言之,当我们尝试将非 json 响应 (text/html/xml) 解组为 json 时会出现此错误。

      【讨论】:

        【解决方案5】:

        如果有人和我有同样的问题,我需要在我的帖子数据上调用 JSON.stringify。

        【讨论】:

          【解决方案6】:

          这个奇怪的错误信息的原因是:

          // When unmarshaling quoted strings, invalid UTF-8 or
          // invalid UTF-16 surrogate pairs are not treated as an error.
          // Instead, they are replaced by the Unicode replacement
          // character U+FFFD.
          

          https://golang.org/src/encoding/json/decode.go

          在我的情况下,我将我的 json 保存为字符串,然后通过以下方式对其进行解析: stringData = JSON.parse(myJsonString)

          我在使用 gin-context-ShouldBind() (https://godoc.org/github.com/gin-gonic/gin#Context.ShouldBind) 并将我的 json 映射到 go 对象时也遇到了同样的错误: 错误是因为它需要一个json作为字符串,所以我在从前端发送我的请求时使用了:JSON.stringify(jsonObject)。

          【讨论】:

            【解决方案7】:

            我遇到了类似的问题,我的错误消息是:

            无效字符“我”正在寻找值的开头

            就我而言,我试图使用json.Unmarshal 解码BSON。 Json 无法识别ISODate 类型,导致此错误。

            【讨论】:

            • @AmitUpadhyay 我通过期待 BSON 而不是 JSON 并使用 bson.Unmarshal 而不是 json.Unmarshal 来解决它。一旦我调试了字节数组,它就有意义了 json 无法解析,因为它类似于 {"date": ISODate("2010-01-01T00:00:00.000Z")}
            【解决方案8】:

            我遇到了类似的问题。对我来说,我省略了授权令牌的第一个字母。所以不是

            "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InJhcGhhZWxuZ0BlbWFpbC5jb20iLCJleHAiOjE2MTM5NTQzMjB9.yPGC937VNAF8Qg05Z1x3fZ3zu_MUs-cA_Iag5-4RcJE"
            

            我用过这个

            "yJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InJhcGhhZWxuZ0BlbWFpbC5jb20iLCJleHAiOjE2MTM5NTQzMjB9.yPGC937VNAF8Qg05Z1x3fZ3zu_MUs-cA_Iag5-4RcJE"
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-06-12
              • 1970-01-01
              • 2018-10-16
              • 2022-10-24
              • 1970-01-01
              相关资源
              最近更新 更多