3

我正在尝试为 i3status 编写一个小替代品,这是一个与符合协议的 i3bar 通信的小程序。他们通过标准输入和标准输出交换消息。

两个方向的流是一个无限的 json 对象数组。从 i3bar 到 i3status 的流的开始(我想替换)如下所示:

[
{"name": "some_name_1","instance": "some_inst_1","button": 1,"x": 213,"y": 35}
,{"name": "some_name_1","instance": "some_inst_2","button": 2,"x": 687,"y": 354}
,{"name": "some_name_2","instance": "some_inst","button": 1,"x": 786,"y": 637}
,{"name": "some_name_3","instance": "some_inst","button": 3,"x": 768,"y": 67}
...

这是代表点击的对象“数组”。阵列永远不会关闭。

我现在的问题是:解析这个的正确方法是什么?

显然我不能使用这个json库,因为这不是一个有效的 json 对象。

4

3 回答 3

6

编写一个自定义读取器函数(或解码器),它执行“流式数组解析”,如下所示:

  1. 读取并丢弃前导空格。
  2. 如果下一个字符不是 a[则返回错误(不能是数组)。
  3. 虽然是真的:
    1. 调用json.Decoder.Decode“下一个”项目。
    2. 产生或处理“下一个”项目。
    3. 读取并丢弃空格。
    4. 如果下一个字符是:
      1. 逗号,然后继续 #3 中的 for 循环。
      2. 然后一个右括号]退出 #3 中的 for 循环。
      3. 否则返回错误(无效的数组语法)。
于 2015-04-03T01:42:31.357 回答
4

我也在为 i3 中的点击事件编写自己的处理程序。这就是我偶然发现这个线程的原因。

Golang 标准库实际上确实做了所需要的(Golang 1.12)。当你问这个问题时不确定它是不是?

// json parser read from stdin
decoder := json.NewDecoder(os.Stdin)

// Get he first token - it should be a '['
tk, err := decoder.Token()
if err != nil {
    fmt.Fprintln(os.Stderr, "couldn't read from stdin")
    return
}
// according to the docs a json.Delim is one [, ], { or }
// Make sure the token is a delim
delim, ok := tk.(json.Delim)
if !ok {
    fmt.Fprintln(os.Stderr, "first token not a delim")
    return
}
// Make sure the value of the delim is '['
if delim != json.Delim('[') {
    fmt.Fprintln(os.Stderr, "first token not a [")
    return
}

// The parser took the [ above
// therefore decoder.More() will return
// true until a closing ] is seen - i.e never 
for decoder.More() {
    // make a Click struct with the relevant json structure tags
    click := &Click{}

    // This will block until we have a complete JSON object
    // on stdin
    err = decoder.Decode(click)
    if err != nil {
            fmt.Fprintln(os.Stderr, "couldn't decode click")
            return
    }
    // Do something with click event
}
于 2019-05-08T08:29:46.073 回答
0

您正在寻找的是 JSON 的 Streaming API。有很多可用的快速谷歌搜索显示项目确实将流媒体列为其高级功能之一。

于 2015-04-02T20:05:30.123 回答