LoginSignup
7

More than 5 years have passed since last update.

posted at

重複したkeyを持つJSONデータをカンマ区切りvalueにまとめる

:pencil2: 経緯

元々xmlだったデータをJSONに変換。その際にkeyの重複に気付かず:innocent:

JSONを参照する実装をしたとき、JSON上は存在するデータが該当しなかったため、今回のバグが発覚 :imp:

:mag: 状況

duplicate_data.json
{
  "foo": "ふー",
  "bar": "ばー",
  "baz": "ばず",
  "foo": "フー",
  "bar": "バー",
  "baz": "バズ"
}

"ふー"を取得したい。

parse.js
const data = require('./duplicate_data.json');
console.log(data);

読み込んで、表示してみる。

result
$ node parse.js
{ foo: 'フー', bar: 'バー', baz: 'バズ' }

Objectにparseされたときに、最後のkeyのvalueのみ格納されていたため、
目的のデータが取得できない。

:bulb: 対応策

Objectとしてparseすると、上記のように最後以外のvalueが消えるので、
ファイルデータを一行ずつ読み込んで、いい感じに加工することにしました:grin:

good_parse.js
const fs = require('fs');
const rs = fs.createReadStream('./duplicate_data.json');
const rl = require('readline');
const rli = rl.createInterface(rs, {});

let pairsAry = [];
let pairs = [];
let l = '';
// 読み込んだファイルを一行ずつ処理
rli.on('line', (line) => {
  // 空白、改行を削除
  l = line.trim();
  // keyとvalueを含めた文字列を配列に分割
  pairs = l.split(':');
  // "や,など不要な部分を削除して配列を返す
  pairs = pairs.map((val) => { return val.replace(/\"|\,/g, '').trim(); });
  // keyとvalueが存在する配列だけ格納
  if (pairs.length === 2) pairsAry.push(pairs);
});

let resultObj = {};
// 読み込みが終了したら実行
rli.on('close', () => {
  let key, value;
  pairsAry.forEach((val) => {
    key = val[0];
    value = val[1];
    if (resultObj.hasOwnProperty(key)) {
      // すでに同じkeyが存在する場合は、カンマ区切りでvalueを追加
      resultObj[key] += ',' + value;
    } else {
      // keyが存在しない場合は、新規でvalueをセット
      resultObj[key] = value;
    }
  });
  // JSONファイルとして、書き出し
  fs.writeFile('parsed_data.json', JSON.stringify(resultObj, null, 2));
});

parsed_data.json
{
  "foo": "ふー,フー",
  "bar": "ばー,バー",
  "baz": "ばず,バズ"
}

めでたしめでたし:clap:

:notebook_with_decorative_cover: 結論

絵文字をつかうと、記事がやわらかい雰囲気になって良い感じでした:kissing_smiling_eyes:

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
7