SAStruts アクションにJSONを返すメソッドを作成してみる - 130単位
↑で書いたコードに対し、気になった点があって直そうと思いました。が、あまりに修正点が多かったので新たに記事にしてみます。
以前のコード
Ajaxでリクエストされ、従業員のリストをJSON形式で返すメソッドです。
@Execute(validator = false) public String ajaxEmployeeList() { List<Employee> employeeList = employeeService.findByDeptId(form.departmentId); HashMap<String, String> map = new HashMap<String, String>(); for (Employee emp: employeeList) { map.put(emp.id, emp.name); } ResponseUtil.write(JSONSerializer.serialize(map), "text/javascript"); return null; }
修正4点
Mapの順序を固定する
HashMapだと、値の順序が保証されません。実際にJSON文字列ではバラバラになってしまっていて、受け側のJavaScriptで扱う際にも影響が出ていました。
HashMap<String, String> map = new HashMap<String, String>();
↓
LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
これで、putした順序通りにJSONに変換されます。ただし期待する結果を得るためには、employeeService#findByDeptId()での照会の際にOrderBy()を利用してソートしておくことが必要です。
また、Mapにはキーの値で自動的にソートされるTreeMapという実装もあるようです。こちらなら、OrderBy()しておく必要はなさそうです。パフォーマンスも含めてどちらが適しているかは未調査です…。
インタフェース型で宣言する
変数などの宣言には、インタフェースを用いるのが良いようです。
LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
↓
Map<String, String> map = new LinkedHashMap<String, String>();
大きな理由としては、コードに柔軟性を持たせるためだと認識しています。『Effective Java』が詳しいです*1。
JSONICを使う
前の記事でも触れましたが、JSONSerializerは@deprecatedとなっているため、JSONICを利用します。
JSONSerializer.serialize(map)
↓
//import net.arnx.jsonic.JSON; が必要
JSON.encode(map)
Content-Typeを「application/json」にする
RFCで定められているように、"application/json"を使うことにします。
修正したコード
以上4点を修正したコードです。
@Execute(validator = false) public String ajaxEmployeeList() { List<Employee> employeeList = employeeService.findByDeptId(form.departmentId); Map<String, String> map = new LinkedHashMap<String, String>(); for (Employee emp: employeeList) { map.put(emp.id, emp.name); } ResponseUtil.write(JSON.encode(map), "application/json"); return null; }
ついでに
これまでの記事で、「デパート」→「部署」に変えておきした。常識的な英語表現っぽくてなんとなく恥ずかしかったので。