🫥

Node.jsのconsole.logでネストが深くても[Object]を出さずに全てを表示する方法

2024/12/03に公開

バックエンドのAPIから取得したデータを確認したい場合などで、ネストが深いデータだと[Object]のように途中から表示されないことがあります。
表示を省略させない方法がいくつかあると知ったのですが、それぞれにメリデメがあったので調べた結果をまとめています。

結論

console.dir(obj, { depth: null });を使いましょう。

問題点を確認する

次のようなデータがあるとします。

const obj = {
  key1: {
    key2: {
      key3: {
        key4: {
          key5: {
            key6: 'value',
          },
        },
      },
    },
  },
};

console.log(obj);と記述すると次のような出力になります。

{ key1: { key2: { key3: [Object] } } }

3階層以降が[Object]になって確認できなくなっています。

コンテンツに関するありそうなデータを作ってみました。

const contents = [
  {
    id: 1,
    username: '山田太郎',
    posts: [
      {
        id: 1,
        title: '今日の手料理: 簡単!鮭の塩麹焼き',
        content:
          '久しぶりに自宅で本格的な料理を作りました。塩麹で下味をつけると、鮭がとても柔らかく仕上がりますよ。',
        tags: ['料理', '和食', '簡単レシピ'],
        likes: 42,
        comments: 7,
        createdAt: '2024-03-15T19:30:00',
      },
      {
        id: 2,
        title: '北海道旅行の思い出 - 札幌編',
        content:
          '先週末に札幌に行ってきました。雪まつり後の美しい街並みと、美味しいラーメンを堪能しました!',
        tags: ['旅行', '北海道', '札幌'],
        likes: 89,
        comments: 15,
        createdAt: '2024-03-22T14:45:00',
      },
    ],
  },
];

同じようにconsole.log()で出力すると、感覚的に階層は深くなさそうなposts内のオブジェクトが[Object], [Object]になっています。

[ { id: 1, username: '山田太郎', posts: [ [Object], [Object] ] } ]

console.log('%o', obj);を使用する

console.log()の第一引数には文字列置換を指定できます。
いくつか用意されていますが%oを指定すると、出力される階層が深くなります。

%o
JavaScript オブジェクトを「最適に有益な書式設定」スタイルで出力します。例えば、DOM 要素は要素インスペクターに現れるのと同じ方法で表示されます。

https://developer.mozilla.org/ja/docs/Web/API/console#例

console.log('%o', obj);と記述すると次のような出力になります。
%oなしだと3階層までだったのが5階層まで出力できています。

{
  key1: {
    key2: { key3: { key4: { key5: [Object] } } }
  }
}

コンテンツデータで試してみても、省略されていたposts内のオブジェクトが出力できているのが確認できます。

[
  {
    id: 1,
    username: '山田太郎',
    posts: [
      {
        id: 1,
        title: '今日の手料理: 簡単!鮭の塩麹焼き',
        content: '久しぶりに自宅で本格的な料理を作りました。塩麹で下味をつけると、鮭がとても柔らかく仕上がりますよ。',
        tags: [ '料理', '和食', '簡単レシピ', [length]: 3 ],
        likes: 42,
        comments: 7,
        createdAt: '2024-03-15T19:30:00'
      },
      {
        id: 2,
        title: '北海道旅行の思い出 - 札幌編',
        content: '先週末に札幌に行ってきました。雪まつり後の美しい街並みと、美味しいラーメンを堪能しました!',
        tags: [ '旅行', '北海道', '札幌', [length]: 3 ],
        likes: 89,
        comments: 15,
        createdAt: '2024-03-22T14:45:00'
      },
      [length]: 2
    ]
  },
  [length]: 1
]

console.log(JSON.stringify(obj, null, 2));を使用する

オブジェクトをJSON文字列に変換するJSON.stringify()を使うと、全てのデータを出力できます。ディープコピーをする場合にも使うことがあるのでイメージしやすいですね。

JSON.stringify()の第三引数であるspaceに数値を指定するとインデントが付けられるようになります。
console.log(JSON.stringify(obj, null, 2));のように2スペースで記述すると次のような出力になります。JSON形式になるのでダブルクオーテーションが付きますが、全てのデータが出力されています。

{
  "key1": {
    "key2": {
      "key3": {
        "key4": {
          "key5": {
            "key6": "value"
          }
        }
      }
    }
  }
}

注意が必要なのは、データ型によっては省略されたり変換されることです。
たとえば次のようなデータをJSON.stringify()で出力してみます。

const data = {
  stringValue: 'value',
  nullValue: null,
  undefinedValue: undefined,
  booleanValue: true,
  arrayValue: [1, undefined, null],
};

nullbooleanは出力されていますが、undefinedが省略されていたり、配列内のundefinednullに置換されています。

{
  "stringValue": "value",
  "nullValue": null,
  "booleanValue": true,
  "arrayValue": [
    1,
    null,
    null
  ]
}

今回は出力を確認するだけなので動作に影響はありませんが、この挙動を知っておいたほうがいいですね。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#:~:text=JSON.stringify() は値をそれを表す JSON 表記に変換します。値は以下のように変換されます。

とはいえ、ログではなくブラウザの表示側にデータをざっと出して確認したい時にJSON.stringify()は便利なので、使い方次第という気もします。

console.dir(obj, { depth: null });を使用する

最後はconsole.dir()を使う方法です。

console.dir()の第二引数であるoptionsにはdepthがあり、出力する階層の数を指定できます。

depth Non-standard Optional
depth 標準外 オプション
A number representing the number of nesting levels to print when an object contains other objects or arrays. The value null means: print all levels. Defaults to 2.
オブジェクトに他のオブジェクトや配列が含まれる場合に表示する入れ子レベルの数を表す数値。値nullは「すべてのレベルを表示する」を意味する。デフォルトは2。

https://developer.mozilla.org/en-US/docs/Web/API/console/dir_static

nullを指定すれば全てのレベルを表示することができるので、console.dir(obj, { depth: null });と記述します。
深い階層でも全て出力されているのがわかります。

{
  key1: {
    key2: {
      key3: { key4: { key5: { key6: 'value' } } }
    }
  }
}

JSON.stringify()で問題になっていたundefinedの省略や置換もされません(当たり前ですが)。

const data = {
  stringValue: 'value',
  nullValue: null,
  undefinedValue: undefined,
  booleanValue: true,
  arrayValue: [1, undefined, null],
};
{
  stringValue: 'value',
  nullValue: null,
  undefinedValue: undefined,
  booleanValue: true,
  arrayValue: [ 1, undefined, null ]
}

というわけで、console.log('%o', obj);でもよくありそうなデータ構造なら問題なく出力できるものの、深い階層のデータを確実に全て出力したい場合にはconsole.dir(obj, { depth: null });を使うのがベストだというのがわかります。

Discussion