jieba.el -- 在Emacs中使用jieba中文分词

作者你好, 自己对 jieba.elsimple-jieba-server.jsstdio-jrpc.js 比较感兴趣. 知道作者是通过 json-rpc 协议来进行调用 nodejieba 的. 所以自己在 terminal 上手动调用 simple-jieba-server.js 进行初步试验.

➜ echo '{"jsonrpc":"2.0", "id":74, "method":"split", "params":["今天天气很好"]}' | node simple-jieba-server.js
{"jsonrpc":"2.0","id":74,"result":["今天天气","很","好"]}SyntaxError: Unexpected end of JSON input
    at JSON.parse (<anonymous>)
    at RPCConnection._receiveRaw (/Users/c/jieba.el/stdio-jrpc.js:66:25)
    at Socket.<anonymous> (/Users/c/jieba.el/stdio-jrpc.js:55:18)
    at Socket.emit (events.js:200:13)
    at emitReadable_ (_stream_readable.js:558:12)
    at onEofChunk (_stream_readable.js:536:5)
    at readableAddChunk (_stream_readable.js:243:5)
    at Socket.Readable.push (_stream_readable.js:210:10)
    at Pipe.onStreamRead (internal/stream_base_commons.js:197:12)
{"jsonrpc":"2.0","id":null,"error":{"code":-32700,"message":"Error during parsing."}}%

可以看到 今天天气很好 已经被成功的分词了. 但是为什么还是会出现 JSON.parse 的错误呢?

作者在 this._receiveRaw 中对接受到的输入进行 JSON 解析.

我看了 stdio-jrpc.js 代码中 this._receiveRaw 是在 RPCConnection 类的构造器中调用的, 第一次调用成功的分词了, 说明第一次成功的解析了 JSON, 但是为什么会出现第二次的调用, 进而导致出现解析的 JSON 是空的, 最终导致抛出异常?

class RPCConnection {

    constructor () {
        this._methodTable = new Map();
        this._currentHandlingId = null;

        process.stdin.setEncoding("utf-8");
        process.stdin.on("readable", () => {
            let data = "";
            let chunk;
            while (true) {
                chunk = process.stdin.read();
                if (chunk === null) {
                    break;
                } else {
                    data += chunk;
                }
            }
            this._receiveRaw(data);
        });
    }

    _sendRaw (rawMsg) {
        process.stdout.write(rawMsg);
    }

    _receiveRaw (rawMsg) {
        let json;
        try {
            json = JSON.parse(rawMsg);
        } catch (e) {
            console.error(e);
            this.sendError(RPCErrors.ParseError());
        }
        if (json != null) {
            let { jsonrpc, id, method, params } = json;
            this._currentHandlingId = id;
            if (jsonrpc !== "2.0") {
                this.sendError(RPCErrors.InvalidRequest());
            } else if (!this._methodTable.has(method)) {
                this.sendError(RPCErrors.MethodNotFound());
            } else {
                let m = this._methodTable.get(method);
                m(params);
            }
        }
        // Reset id
        this._currentHandlingId = null;
    }
1 个赞

是echo的问题,echo会在每个打印的参数后面加一个空格。

echo "a"

得到a<space>然后node把这个空格当作一个新的JSON来parse,就出错了

好的, 谢谢解答.

为什么不考虑 cjieba 呢?

原来有人提到过。

默认的brew安装了node 17, 实测无法编译. 通过一些搜索, 使用brew 安装了nvm, 使用nvm安装了node 11. 安装成功.

但是启动时还是报错. [jsonrpc] Server exited with status 1 [2 times]

看到上面的同学的回复, 自己也在命令行中试了一下. echo ‘{“jsonrpc”:“2.0”, “id”:74, “method”:“split”, “params”:[“今天天气很好”]}’ | node simple-jieba-server.js

错误信息和那位同学一致.

但是楼主说是因为多加入了一个空格. 于是我又用printf试了一下. 这应该没有空格吧.

printf ‘%s’ ‘{“jsonrpc”:“2.0”, “id”:74, “method”:“split”, “params”:[“今天天气很好”]}’ | node simple-jieba-server.js printf ‘{“jsonrpc”:“2.0”, “id”:74, “method”:“split”, “params”:[“今天天气很好”]}’ | node simple-jieba-server.js

两次请求和echo是一样的. 都是同样的错误信息.

我应该怎么做来调试这个问题?

这个我有空看看吧,太久没用这个了 :sweat: