>我有一个简短的Go程序,它为多个包运行go list -json
命令,将每次命令运行的输出存储在json中。RawMessage,附加每个 json。RawMessage 成一片 json。RawMessages,然后在连接每个 json 后将结果返回到服务器。将原始消息组合在一起并压缩 json。但是,当我运行json.Compact
时会产生一条错误消息,我找不到其来源。谷歌搜索此错误消息显示,大多数似乎遇到它的人 - 无论是无效,
还是其他角色 - 都很难找到它的来源。
invalid character ',' looking for beginning of value
带有注释的代码可以在 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/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 程序中也遇到了相同的错误消息,但该错误消息在 HTTP 响应错误中,当我的 HTTP 响应解析器需要 JSON 时,采用 HTML 格式。
对我来说,解决方案是更改我的请求以包括将Content-Type
标头设置为 application/json
.如何执行此操作取决于您碰巧使用的 http 客户端库;如果您有权访问http.Header
核心类型,则可以使用 .Set(...)
设置标头。
我意识到此修复程序的范围可能不适用于原始问题,但是我在谷歌搜索后首先来到这里,并认为这会对其他人有所帮助,因为乍一看该消息并不是特别明显。提示是无效的<
字符是错误/响应中的第一个 HTML 字符,这可能是请求类型未设置为 application/json
的结果,因此服务器使用非 JSON 响应进行响应。
,问题是我试图解析已经解析的JSON。
我也遇到了这个错误"无效字符'N'寻找值的开头"。此错误是在"将非 json 响应解组为 json "时出现的。我期待一个 json 响应,所以编写了 go 代码将其解组为 json。但是,由于URL更改,我得到的响应是文本,即。"404 未找到"错误,无法将其解组为 json。"查找值开头的字符'N'无效">
因此,总而言之,当我们尝试将非 json 响应(text/html/xml(解组为 json 时,会出现此错误。
毛骨悚然的错误消息的原因是:
// 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(。
如果有人和我有同样的问题,我需要在我的帖子数据上调用 JSON.stringify。
我遇到了类似的问题,我的错误消息是:
查找值开头的无效字符"I">
就我而言,我试图使用 json.Unmarshal
解码BSON
。Json 无法识别导致此错误的ISODate
类型。
我也有类似的问题。对我来说,我省略了授权令牌的第一个字母。所以而不是
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InJhcGhhZWxuZ0BlbWFpbC5jb20iLCJleHAiOjE2MTM5NTQzMjB9.yPGC937VNAF8Qg05Z1x3fZ3zu_MUs-cA_Iag5-4RcJE"
我用了这个
"yJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InJhcGhhZWxuZ0BlbWFpbC5jb20iLCJleHAiOjE2MTM5NTQzMjB9.yPGC937VNAF8Qg05Z1x3fZ3zu_MUs-cA_Iag5-4RcJE"