2016/08/03

javax.json.Json めんどくさすぎる

var jsonObject = JSON.parse("{\"key\":\"value\"}");
var jsonArray = JSON.parse("[1,true,\"word\"]");
var jsonString = JSON.stringify({key:"value"});
のjavascriptみたいに一行でString ⇄ JsonObject変換したいけど javax.json.JsonのAPIがめんどくさすぎる。特にJsonWriterとか使わない使いたくない場合。

Lazy Man approach


使い方はjsに少し似ていて lazyなおれにとってはマシかと。。。
JsonObject jsonObject = JsonUtils.parse("{\"key\":\"value\"}");
JsonArray jsonArray = JsonUtils.parseArray("[1,true,\"word\"]");
String jsonString = JsonUtils.stringify(jsonObject);

復習

使い方をいつもわすれるので ちょっとメモを

JsonObjectやJsonArrayの構築

基本的に Json.createObjectBuilder().xyz.build()Json.createArrayBuilder().abc.build()でオブジェクトやアレーを入れっこ作っていく。xyzとabcとはadd(...)関数のこと
例えば、このようなjsonオブジェクトを組み立てたいとしたら
{
  keyString: "String",
  keyBoolean: true,
  keyArraySimple: [
    1,
    11,
    111
  ],
  keyArrayObject: [{
      lang: "ja",
      where: "どこ"
    },{
      lang: "es",
      where: "donde"
  }],
  keyObject: {
    git: "svn",
    github: "sourceforge"
  },
  keyNull: null
}
このように書ける
JsonObject json = Json.createObjectBuilder()
        .add("keyString", "string")
        .add("keyBoolean", true)
        .add("keyArraySimple", Json.createArrayBuilder()
                .add(1)
                .add(11)
                .add(111).build())
        .add("keyArrayObject", Json.createArrayBuilder()
                .add(Json.createObjectBuilder()
                        .add("lang", "ja")
                        .add("where", "どこ").build())
                .add(Json.createObjectBuilder()
                        .add("lang", "es")
                        .add("where", "sourceforge").build()))
        .add("keyObject", Json.createObjectBuilder()
                .add("git", "svn")
                .add("github", "sourceforge").build())
        .addNull("keyNull").build();
注意 JsonObjectJsonArrayはinmutable。mutateできるのはJsonObjectBuilderJsonArrayBuilderの時点までだ。つまり.build()メソッドの直前まで。

型を調べる

例えば JsonArrayJsonObjectの中身が固定ではないとき getHogeHogeしてClassCastExceptionをキャッチするより get() してから getValueType() を行う方がよさそう.
JsonArray jsonArray = Json.createArrayBuilder()
         .add("some string")
         .add(true)
         .add(1)
         .addNull().build();
for (int i = 0; i < jsonArray.size(); ++i) {
    JsonValue value = jsonArray.get(i);
    switch (value.getValueType()) {
    case STRING:
        String someString = jsonArray.getString(i);
        ...
        break;
    case ARRAY:
        boolean positive = jsonArray.getBoolean(i);
        ...
        break;
    case NULL:
        ...
        break;
    ...
    default:
        ...
        break;
    }
}

HttpServletRequestのbodyをJsonObjectに直接読む

前はJsonReaderやJsonWriterを使いたくないとかぶつぶつ言ったかもしれないけど、やはり使えるならば使った方がよさそう。
リクエストのボディをStringにしてからまたJsonObjectにする方がめんどくさい。一発でreaderから直接JsonObjectしよう。書き出しのときは 一旦Stringにしてからじゃないやりかたを今のところ思いつかない。
public class MyServlet extends HttpServlet {
    @Override 
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

        // Only needed when client does not set it properly. 
        // IMO, Ideally this should not be needed
        request.setCharacterEncoding(StandardCharsets.UTF_8.toString());

        // リクエストボディを読込
        JsonReader bodyJsonReader = Json.createReader(new BufferedReader(request.getReader()));
        JsonObject bodyJsonObject = bodyJsonReader.readObject();
        
        ...

        // リスポンスを返却
        String jsonString = JsonUtils.stringify(Json.createObjectBuilder.build());
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
        response.setContentType("application/json");
        response.getWriter().write(jsonString);
    }
}

0 comments :