BeginnerEngineerBlog
中の人
中の人

【php json_encode】json_encodeするとフロントでArrayになったりObjectになったりした

公開: 2024-02-28 01:22
更新: 2024-04-04 02:03
35
php json_encode
ajaxで利用する関数を修正したらエラーが出て、忘れた頃にハマるだろうと感じたので備忘録として紹介します

こんにちは!
中の人です

最近フロントに値を返す非同期処理の関数を修正したら、それまで動いていたフロントの処理が動かなくなりました
もともとArray型で取得していたものが、Object型になっていたのが原因でした

でも返す値同じように配列なんだけど。。
なんでやねん

と動作を確認していたところ、タイトルのように配列になったりオブジェクトになったりする挙動がありましたので紹介します!


どういうことか



Array型で取得していたのに、いつの間にかObject型になっていました

上記のコンソール出力見て、「あーはいはい」と勘づいた方はお疲れ様でした!笑

今後もBeginnerEngineerBlogをよろしくお願いします!


サンプルコード


📂 root/index.html

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script
              src="https://code.jquery.com/jquery-3.7.1.min.js"
              integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo="
              crossorigin="anonymous"></script>
    <title>Document</title>
</head>
<body>
    <script>
        $(function () {
            $('#do_ajax').on('click', function () {
                doAjax();
            });
            function doAjax () {
                $.ajax({
                    url: './api.php',
                    type: 'GET',
                    dataType: 'json',
                }).done(function (data, textStatus, jqXHR) {
                    console.log(data);
                }).fail(function (jqXHR, textStatus, errorThrown) {
                    console.log(jqXHR, textStatus, errorThrown);
                });
            }
        });
    </script>

    <button type="button" id="do_ajax">ajax</button>
</body>
</html>

Arrayになる値


📁 root/api.php

<?php

$json = json_encode([
    0 => 'Hello, Beginner!',
    1 => 'Hello, Engineer!',
]);


echo $json;
exit;

Objectになる値


📁 root/api.php

<?php

$json = json_encode([
    0 => 'Hello, Beginner!',
    2 => 'Hello, Engineer!',
]);

echo $json;
exit;

注目するのは返り値の配列のkeyです


配列のkeyが指定されていない、または0から順番に振られている場合はArray型になって、それ以外はObject型になる


みたいです

試しに

📁 root/api.php

<?php

$json = json_encode([
    [
        'Hello, Beginner!', // keyなし
        'Hello, Engineer!',
    ],
    [
        0 => 'Hello, Beginner!', // 0から順番にkeyあり
        1 => 'Hello, Engineer!',
    ],
    [
        1 => 'Hello, Beginner!', // 1から順番にkeyあり
        2 => 'Hello, Engineer!',
    ],
    [
        0 => 'Hello, Beginner!', // 0から歯抜けのkeyあり
        2 => 'Hello, Engineer!',
    ]
]);

echo $json;
exit;

これの実行結果は、


keyなし、0から順番にkeyありはArray型になってますが、1から順番にkeyあり、0から歯抜けのkeyありは、Object型になってます

Why!(゚∀゚ )


phpのjson_encodeの仕様っぽい


PHP: json_encode - Manualに、それっぽい箇所ありました

注意:
配列をエンコードする場合、もし配列のキーが 0 からはじまる連続した数値でなければ、 すべてのキーを文字列としてエンコードします。 そして、個々のキー/値のペアを明示的に指定します。

つまり、0から始まる連続した数値なら、keyを文字列にしないということっぽいですね

デバッグの結果を見てみると


$jsonで出力されている中身は

"[["Hello, Beginner!","Hello, Engineer!"],["Hello, Beginner!","Hello, Engineer!"],{"1":"Hello, Beginner!","2":"Hello, Engineer!"},{"0":"Hello, Beginner!","2":"Hello, Engineer!"}]"

keyなし、0から順番にkeyありは、どちらもkeyがありません。
が、残りの2つはkeyが文字列で存在していますね

へー(゚∀゚ )


明示して固定したい場合



こちらにすでにこの挙動に気づいた方が注意喚起してくれていました

配列で受け取りたい場合


array_valuesを利用する
📁 root/api.php

<?php

// 配列をarray_values関数でkeyを振り直す
$json = json_encode([
    array_values([
        'Hello, Beginner!',
        'Hello, Engineer!',
    ]),
    array_values([
        0 => 'Hello, Beginner!',
        1 => 'Hello, Engineer!',
    ]),
    array_values([
        1 => 'Hello, Beginner!',
        2 => 'Hello, Engineer!',
    ]),
    array_values([
        0 => 'Hello, Beginner!',
        2 => 'Hello, Engineer!',
    ]),
]);

echo $json;
exit;

これは


全てkeyが振り直されてArray型になります

Objectで受け取りたい場合


📁 root/api.php

<?php

$json = json_encode([
    [
        'Hello, Beginner!',
        'Hello, Engineer!',
    ],
    [
        0 => 'Hello, Beginner!',
        1 => 'Hello, Engineer!',
    ],
    [
        1 => 'Hello, Beginner!',
        2 => 'Hello, Engineer!',
    ],
    [
        0 => 'Hello, Beginner!',
        2 => 'Hello, Engineer!',
    ]
// 👇 こいつを指定
], JSON_FORCE_OBJECT);

echo $json;
exit;

json_encodeの第二引数を指定します

これは


全てObject型になりました

ほー(゚∀゚ )< コンナフラグアッタンヤナシラン


終わりに


最初js側の問題かと思って調べたのですが、そういった記事がなく、php側をデバッグして気づきました
もともとkeyが0から順番に振られる仕様だったところ、array_filterで抽出する値を調整したところ、keyが順番通りでなくなってObjectとして渡されていたみたいでした

これから気をつけようと思いました

おつ!
0
0
0
0
通信エラーが発生しました。
似たような記事