如何找到“无效字符”,“寻找值的开头”错误信息

时间:2015-03-24 23:36:27

标签: go

我有一个简短的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

}

8 个答案:

答案 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"