Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何跳过&x27;噪音';在JSON对象流中?_Json_Parsing_Go_Io - Fatal编程技术网

如何跳过&x27;噪音';在JSON对象流中?

如何跳过&x27;噪音';在JSON对象流中?,json,parsing,go,io,Json,Parsing,Go,Io,尝试获取以下代码以跳过JSON数据对象流中的解析错误噪声。基本上,我希望它跳过错误:…行,继续下一条可解析记录 json.Decoder的索引集有限,因此不清楚如何将解码器的索引向前移动(比如一次移动一个字节)以越过噪声 io.Reader有一些方法可以跳到行尾(或者至少尝试一次跳过一个字符),但这样做不会(可以理解)影响json.Decoder的搜索状态 有没有干净的方法可以做到这一点 得到: 想要: 我认为这样做的“正确”方法是,由于流本身不是有效的JSON(即使没有错误,JSON文档也必

尝试获取以下代码以跳过JSON数据对象流中的解析错误噪声。基本上,我希望它跳过
错误:…
行,继续下一条可解析记录

json.Decoder
的索引集有限,因此不清楚如何将解码器的索引向前移动(比如一次移动一个字节)以越过噪声

io.Reader
有一些方法可以跳到行尾(或者至少尝试一次跳过一个字符),但这样做不会(可以理解)影响
json.Decoder
的搜索状态

有没有干净的方法可以做到这一点

得到:

想要:

我认为这样做的“正确”方法是,由于流本身不是有效的JSON(即使没有错误,JSON文档也必须有一个根条目,这是一系列无效的根对象),将预解析为单个有效的JSON文档,并分别解组。使用例如丢弃非JSON行,并将其他行正常地
Unmarshal
逐行读取流


请参阅此处的工作示例:

虽然不是很干净,但可以使用JSON解码器的
缓冲
方法访问底层读取器,该读取器仍应指向导致错误的字节,并在必要时将其包装在缓冲读取器中。然后,您可以读取单个字节,直到遇到一个有效的JSON开始对象字节
{
,并且未读该字节(在任何实现中至少有1个字节可以未读),以将该字节推回到缓冲流中

然而

IMHO,正确的处理方法要求您接收一个JSON对象的JSON数组,允许您通过提供一个带有
*事件
方法接收器的
解组JSON
方法来处理表示
事件
的每个JSON对象的手动标记化,但是如果您无法获得该方法,那么这并不重要r、 您需要修改提供的解决方案,使其在必要时工作,假设这是可能的。一种可能的补救方法是设置标志,并在检测到有效的JSON对象时取消设置:

    objectDetected := false
    i := 0
decodeLoop:
    ...
                if b == '{' {
                    // If we already encountered an object and found ourselves here again,
                    // it's not really a valid JSON object.
                    if objectDetected {
                        break
                    }
                    objectDetected = true
                    br.UnreadByte()
                    ...
        fmt.Printf("%3d: %+v\n", i, ev)
        objectDetected = false
    } // decode loop end
}

为简单起见,我使用了一个字符串,但实际上数据是通过web服务流(不是我所有的),因此没有文档本身。我想解析可解析的数据并跳过任何垃圾不可解析的字节。每个记录都在一行上-因此跳到行的末尾(“\n”)将是可接受的解决方案。不管是字符串还是来自web服务。过程是一样的,扫描器仍然可以工作。请参阅我的编辑中的游乐场示例。我的评论与您关于这是无效JSON的声明有关(除了解析错误)。一个有效的JSON对象流对解码器是有效的。它可能会被一些解码器接受,但它不是有效的JSON,因此您不能合理地期望每个解码器都接受它。这就是为什么在尝试解码之前必须先将其预处理为不受干扰的有效JSON文档的原因。http-sse使用单个记录。它们不会开始解码带有“[”的JSON流。这实际上是我想要实现的:如果出现解析错误,请将搜索指针一次移动1个字节,直到读取有效记录。仅在“{”上搜索不一定有效,因为“噪声”可能包含“{”。因此,很好地使用
bufio.Reader
Decoder.Buffered
来实现这一点。仅供参考:JSON“流”,虽然在游乐场示例中是静态的,但实际上它来自HTTP-SSE web服务(不在我们的控制范围内),需要实时处理"不可能。这是有道理的。我不确定您是否有权修改服务。您的流与Linux上的i3status程序类似,它输出一个包含版本信息的单个对象,然后是一个包含信息的无限/不完整的对象数组,这些对象包含要在状态栏上打印的信息。y和我们的情况是,在流打印感兴趣的对象之前,只有一个单独的对象。可以跳过流开头的已知异常项,但整个流中的异常要复杂一些。
  1: {T:2017-11-02 16:00:00 -0400 -0400 Desc:window opened}
  2: {T:2017-11-02 16:30:00 -0400 -0400 Desc:window closed}
  3: {T:2017-11-02 16:41:34 -0400 -0400 Desc:front door opened}
parse error: %s invalid character 'E' looking for beginning of value
  1: {T:2017-11-02 16:00:00 -0400 -0400 Desc:window opened}
  2: {T:2017-11-02 16:30:00 -0400 -0400 Desc:window closed}
  3: {T:2017-11-02 16:41:34 -0400 -0400 Desc:front door opened}
  4: {T:2017-11-02 16:41:40 -0400 -0400 Desc:front door closed}
...
decodeLoop:
    for decodeStream.More() {
        i++
        var ev event
        if err := decodeStream.Decode(&ev); err != nil {
            r := decodeStream.Buffered()
            br, ok := r.(*bufio.Reader)
            if !ok {
                br = bufio.NewReader(r)
            }
            for {
                b, err := br.ReadByte()
                if err != nil {
                    // Whether EOF or not, there's nothing left to do except
                    // break the loop to trigger the "parse error" statement.
                    break
                }
                // A (potentially) valid JSON object was found;
                // create a new decoder associated with the same decodeStream var
                // using the new buffered reader and continue decoding.
                if b == '{' {
                    br.UnreadByte()
                    decodeStream = json.NewDecoder(br)
                    continue decodeLoop
                }
            }
            fmt.Println("parse error: %s", err)
            break
        }
        ...
    objectDetected := false
    i := 0
decodeLoop:
    ...
                if b == '{' {
                    // If we already encountered an object and found ourselves here again,
                    // it's not really a valid JSON object.
                    if objectDetected {
                        break
                    }
                    objectDetected = true
                    br.UnreadByte()
                    ...
        fmt.Printf("%3d: %+v\n", i, ev)
        objectDetected = false
    } // decode loop end
}