我试图为i3status编写一个小替代品,这是一个与符合this协议的i3bar通信的小程序。他们通过stdin和stdout交换了messeages。
两个方向的流是一个无限的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对象。
答案 0 :(得分:4)
编写一个自定义读取器函数(或Decoder),它执行“流式数组解析”,如下所示:
[
,则返回错误(不能是数组)。json.Decoder.Decode
调入“下一个”项目。,
然后继续#3中的for循环。]
然后退出#3中的for循环。答案 1 :(得分:1)
我也正在为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
}
答案 2 :(得分:0)
您正在寻找的是JSON的Streaming API。有很多可用的快速谷歌搜索显示this项目,它将Streaming列为其中一项先进功能。