我有一个简短的Go程序,它为几个包运行go list -json
命令,将每个命令运行的输出存储在json.RawMessage中,将每个json.RawMessage追加到一个json.RawMessages切片中,在将每个json.RawMessages连接在一起并压缩json之后,将结果返回给服务器。但是,当我运行json.Compact
时无法找到源代码时会出现错误消息。谷歌搜索此错误消息表明,大多数似乎遇到它的人 - 无论是无效的,
还是其他角色 - 都很难找到它的来源。
invalid character ',' looking for beginning of value
带有注释的代码可以在这里查看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
}
答案 0 :(得分:8)
首先,正如已经评论过的,你确定你不能使用
直接使用go/build
包而不是运行go list
?
我不会在HTTP处理程序中使用println
(或fmt.Println
)。最好使用log.Println
和/或将错误输入ResponseWriter
。此外,最好将ListenAndServe
电话与log.Fatal
打包在一起。
打印/记录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
的错误,所以不清楚是否应该是空的,或者由于前一个错误它是否为空。从不忽略错误返回!)
答案 1 :(得分:2)
我在Go程序中也遇到了相同的错误消息,但是当我的HTTP响应解析器期望JSON时,错误消息在HTTP响应错误内,以HTML格式。
对我来说,解决方案是更改我的请求,将Content-Type
标题设置为application/json
。如何执行此操作取决于您正在使用的http客户端库;如果您有权访问http.Header
核心类型,则可以使用.Set(...)
设置标头。
我意识到这个修复程序的范围可能不适用于原始问题,但是我在google搜索后首先来到这里并认为这会对其他人有所帮助,因为乍一看这个消息并不是特别明显。提示是无效的<
字符是错误/响应中的第一个HTML字符,这可能是请求类型未设置为application/json
的结果,因此服务器以非JSON响应响应。
答案 2 :(得分:2)
以防万一,
对我来说,问题是我试图解析已经解析的JSON。
答案 3 :(得分:1)
此怪异错误消息的原因是:
// 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)。
答案 4 :(得分:1)
我也遇到了这个错误“无效字符‘N’正在寻找值的开头”。 在“将非 json 响应解组为 json”时出现此错误。我期待 json 响应,因此编写了 go 代码将其解组为 json。但是,由于 URL 更改,我得到的响应是文本,即。 “404 Not found”错误,无法解组为 json。 “无效字符 'N' 正在寻找值的开头”
总而言之,当我们尝试将非 json 响应 (text/html/xml) 解组为 json 时,会出现此错误。
答案 5 :(得分:0)
如果有人遇到与我相同的问题,我需要在我的帖子数据上调用JSON.stringify。
答案 6 :(得分:0)
我遇到了类似的问题,错误消息是:
无效字符“我”正在寻找值的开头
在我的情况下,我尝试使用BSON
解码json.Unmarshal
。 Json无法识别导致此错误的ISODate
类型。
答案 7 :(得分:0)
我有一个类似的问题。对我来说,我省略了授权令牌的第一个字母。所以代替
func removeRow(at row: Int) {
array.remove(at: row)
self.loadTable()
}
override func table(_ table: WKInterfaceTable, didSelectRowAt rowIndex: Int) {
let delete = WKAlertAction(title: "Delete Item", style: .default) {
self.removeRow(at: rowIndex)
self.userDefaults.setValue(self.array, forKey: "items")
}
let cancel = WKAlertAction(title: "cancel", style: .cancel) {}
self.presentAlert(withTitle: "Alert", message: "Do you want to delete this item?", preferredStyle: .alert, actions: [delete,cancel])
}
我用了这个
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InJhcGhhZWxuZ0BlbWFpbC5jb20iLCJleHAiOjE2MTM5NTQzMjB9.yPGC937VNAF8Qg05Z1x3fZ3zu_MUs-cA_Iag5-4RcJE"