LoginSignup
6
7

More than 5 years have passed since last update.

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

Posted at

: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:

6
7
1

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
  3. You can use dark theme
What you can do with signing up
6
7