JavaScript
Chrome
WebAPI
JSON

Chromeでjsonのkeyを数字にしている場合、勝手に昇順にされる件。

More than 3 years have passed since last update.

筆者環境:MacOSX Yosemite, Google Chromeバージョン 46.0.2490.86 (64-bit)

表題通り、ありがた迷惑な機能。

これはV8 JavaScript EngineのECMAScript準拠でバグではない模様。

5年前くらい前から変わっていない。

firefoxでは降順ソートは維持され、問題ないことを確認。


問題のIssue 37404 - chromium - Chrome reorders keys in the dictionary (object) http://bit.ly/1Qw0utr


こんな感じに成形して、keyを数字で降順ソートしたが、勝手にkeyで昇順にソートされる。

{

1444275582: {
url: "https://instagram.com/p/8j9S8_r_BE/",
img: "https://scontent.cdninstagram.com/hphotos-xap1/t51.2885-15/s640x640/sh0.08/e35/12120292_917670381655742_1569021259_n.jpg"
},
1444545530: {
url: "https://instagram.com/p/8sALlWAfUJ/",
img: "https://scontent.cdninstagram.com/hphotos-xtp1/t51.2885-15/e15/12106290_1294775143882158_1454631624_n.jpg"
}
}


対策

created_atのkeyだけで降順ソートでjson成形

{

{
created_at: "1447984282",
url: "https://instagram.com/p/-SfFKzy73D/",
img: "https://scontent.cdninstagram.com/hphotos-xfp1/t51.2885-15/ s640x640/sh0.08/e35/12256594_516826635166064_1483786264_n.jpg"
},
{
created_at: "1447984163",
url: "https://instagram.com/p/-Se2neyurm/",
img: "https://scontent.cdninstagram.com/hphotos-xfp1/t51.2885-15/e15/12230899_1538400876451449_364138165_n.jpg"
}
}


解決方法


バックエンド側でjsonを吐き出す実装を変える(php)

<?php

// APIから取得したデータを成形
foreach($result["data"] as $k => $v){
$insta_arr[$k]["created_at"] = $v["created_time"];
$insta_arr[$k]["url"] = $v["link"];
$insta_arr[$k]["img"] = $v["images"]["standard_resolution"]["url"];
//いったんソートするキーを配列で取り出して、
$created_at_arr[$k] = $v["created_time"];
}

// keyで降順
array_multisort($created_at_arr ,SORT_DESC,$insta_arr);
echo json_encode($insta_arr);
exit;


js側でソート(lodash)

    _.map(_.sortByOrder(insta_arr, ['created_at'], ['desc']), _.values);


参考

Issue 37404 - chromium - Chrome reorders keys in the dictionary (object) http://bit.ly/1Qw0utr

Issue 164 - v8 - Wrong order in Object properties interation - V8 JavaScript Engine

https://code.google.com/p/v8/issues/detail?id=164

Google Chromeでjsonオブジェクトを扱う際に、勝手にキーでソートされたよ

http://log.miraoto.com/2013/02/738/