文系からでもプログラミングできました!IT関係の情報を書いていきます。

プログラマーinfo

Elasticsearch

Elasticsearchへのjsonリクエストのパースエラー(json_e_o_f_exception)の3つの原因

投稿日:

Express(Node.js)からエラスティックサーチにリクエストを送ったところ以下のようなエラーが帰ってきました。

日本語文字列の保存には失敗して英語の文字列の更新は成功するのでエンコーディングの問題かと思い込んでいたのですが、最終的にはContent-Lengthをbyte長でなく文字列長に設定していたのが原因でした。

送ったリクエスト(一部)

const bodyString = JSON.stringify({title: 'タイトル', content: 'コンテンツ'});
console.log(`JSON_STRINGIFIED_REQUEST: ${bodyString}`);
const options = {
    'host': 'localhost',
    'port': 9200,
    'method': 'POST',
    'path': path,
    'headers': {
        'Content-Type': 'application/json;charset=utf-8',
        'Content-Length': bodyString.length
    }
};
const req = http.request(options, res => {

 

レスポンス

{"error":{"root_cause":[{"type":"json_e_o_f_exception","reason":"Unexpected end-of-input: expected close marker for Object (start marker at [Source: org.elasticsearch.transport.netty4.ByteBufStreamInput@2976b6b2; line: 1, column: 8])\n at [Source: org.elasticsearch.transport.netty4.ByteBufStreamInput@2976b6b2; line: 1, column: 145]"}],"type":"json_e_o_f_exception","reason":"Unexpected end-of-input: expected close marker for Object (start marker at [Source: org.elasticsearch.transport.netty4.ByteBufStreamInput@2976b6b2; line: 1, column: 8])\n at [Source: org.elasticsearch.transport.netty4.ByteBufStreamInput@2976b6b2; line: 1, column: 145]"},"status":500}

僕の場合はContent-Lengthの設定が原因でしたが、想定できた原因に関して以下に整理しておきます。

考えられる原因1 – 送信する文字コードがutf-8でない

Elasticsearchはデフォルトでutf-8の文字コードのデータを受け取ります。なので、リクエストヘッダーに以下の記述が必要です。

'Content-Type': 'application/json;charset=utf-8'

考えられる原因2 – Content-Lengthが間違っている

僕がこのケースだったのですが、ヘッダーのContent-Lengthが正しく設定されていないと、jsonデータが全て読み込まれないためパースエラーになります。

僕のケースでは、http.requestの設定を以下のようにする必要がありました。

const options = {
              'host': 'localhost',
              'port': 9200,
              'method': 'POST',
              'path': path,
              'headers': {
                  'Content-Type': 'application/json;charset=utf-8',
                  'Content-Length': Buffer.byteLength(bodyString, 'utf-8')
              }
          };

 

Buffer.byteLengthは、bodyString(文字列)をutf-8でbyte列に変換してbyte長を計算してくれます。

 

考えられる原因3 – 送るJson文字列の構造が間違っている

一番基本的な部分ですね。JSON.stringifyからJson文字列を生成していれば問題ないと思いますが、そうではなく手打ちで文字列を記述していた場合などは要注意です。

-Elasticsearch

Copyright© プログラマーinfo , 2018 All Rights Reserved Powered by STINGER.