【Androidでデータやファイルと戯れる】JSONTokenerを使用する
JSONとはRFC 4627とRFC 7159で規定される構造化された文字列のことです。
AndroidでJSONを取り扱うにはorg.jsonパッケージを使用します。
今回は、JSONTokenerを使い、特定のJSON文字列(String)からJSONObjectを作成します。
JSONTokenerとは
JSONTokenerは入力文字列からJSON文字列を抽出するクラスです。操作対象の文字列をコンストラクタの引数に取ります。
JSONTokenerにはコンストラクタで引数にした文字列を操作するメソッドが定義されています。
しかし、一般的に使用するのはコンストラクタとnextValueメソッドです。
JSONTokenerのカレントポジションを移動させる
JSONTokenerは内部的にカレントポジションを持っています。JSONTokenerで定義されているメソッドを用いてカレントポジションを移動させながら操作対象文字列を操作します。
char next() |
カレントポジションの文字を1つ取得し、カレントポジションを1進めます。 |
String next(int length) | カレントポジションの文字からlengthの長さの文字列を取得し、カレントポジションをlength分進めます。 |
char next(char c) |
次の一文字がcと一致する場合はその文字を取得し、カレントポジションを1進めます。 一致しない場合はJSONExceptionが発生する。 |
String nextString(char quote) |
カレントポジションから引数に渡した文字と一致する文字までの文字列を取得し、カレントポジションを一致した文字まで進める。 一致する文字がない場合はJSONExceptionが発生する。 |
String nextTo(char excluded) |
カレントポジションから引数に渡した文字と一致する文字までの文字列を取得し、カレントポジションを一致した文字まで進める。 一致する文字がない場合はカレントポジションから末尾までの文字列が取得し、カレントポジションを末尾まで進める。 |
String nextTo(String excluded) | カレントポジションから引数に渡した文字列の中で一致する文字までの文字列を取得し、カレントポジションを一致した文字まで進める。 文字列の中に一致する文字がない場合はカレントポジションから末尾までの文字列が取得し、カレントポジションを末尾まで進める。 |
String nextClean() | カレントポジションの次に来る文字が空白ではなく、コメントに属していない場合に次の文字を取得し、カレントポジションを次に進める。 |
char skipTo(char to) |
カレントポジションを引数の文字まで進める。 引数の文字が存在しない場合はカレントポジションは移動しません。 |
void skipPast(String thru) |
カレントポジションを引数の文字列と完全一致するまで進める。 引数の文字が存在しない場合はカレントポジションは移動しません。 |
boolean more() | 次の文字がある場合はtrue、末尾まで到達した場合はfalseが返却されます。 |
void back() | カレントポジションを一つ戻す。 |
String toString() | カレントポジションと入力文字列を表示する |
JSONException syntaxError(String message) |
下記のようなメッセージを持つJSONExceptionを生成します。 org.json.JSONException: [String message] at character [カレントポジション] of [操作文字列] |
Object nextValue() | カレントポジションからJSONObject・JSONArray・String・Boolean・Integer・Long・Double・NULL等の意味のある文字列を取得し、各型に変換します。 |
static int dehexchar(char hex) | 16進数文字(‘0’~’F’)を10進数(0~15)に変換します、16進数以外のcharは-1に変換されます。 |
JSONTokenerを使う
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); JSONObject jsonObject = createJSONTokener(); } private JSONObject createJSONTokener() { JSONObject jsonObject = null; try { String nextTestString = "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ"; JSONTokener nextJSJsonTokener = new JSONTokener(nextTestString); // カレントポジションと対象文字列を表示する Log.d("JSONTokener", "String toString(): " + nextJSJsonTokener.toString()); // カレントポジションの文字を1つ取得し、カレントポジションを1進める Log.d("JSONTokener", "char next(): " + nextJSJsonTokener.next()); // カレントポジションと対象文字列を表示する Log.d("JSONTokener", "String toString(): " + nextJSJsonTokener.toString()); // カレントポジションの文字から引数の値分の長さの文字列を取得し、カレントポジションを引数の値分進める Log.d("JSONTokener", "String next(int length): " + nextJSJsonTokener.next(2)); // カレントポジションと対象文字列を表示する Log.d("JSONTokener", "String toString(): " + nextJSJsonTokener.toString()); // 次の一文字が引数に渡した文字と一致する場合はその文字を取得し、カレントポジションを1進める。一致しない場合はJSONExceptionが発生する。 Log.d("JSONTokener", "char next(char c): " + nextJSJsonTokener.next('d')); // カレントポジションと対象文字列を表示する Log.d("JSONTokener", "String toString(): " + nextJSJsonTokener.toString()); // カレントポジションから引数に渡した文字と一致する文字までの文字列を取得し、カレントポジションを一致した文字まで進める。 // 一致する文字がない場合はJSONExceptionが発生する。 Log.d("JSONTokener", "String nextString(char quote): " + nextJSJsonTokener.nextString('k')); // カレントポジションと対象文字列を表示する Log.d("JSONTokener", "String toString(): " + nextJSJsonTokener.toString()); // カレントポジションから引数に渡した文字と一致する文字までの文字列を取得し、カレントポジションを一致した文字まで進める。 // 一致する文字がない場合はカレントポジションから末尾までの文字列が取得し、カレントポジションを末尾まで進める。 Log.d("JSONTokener", "String nextTo(char excluded): " + nextJSJsonTokener.nextTo('o')); // カレントポジションと対象文字列を表示する Log.d("JSONTokener", "String toString(): " + nextJSJsonTokener.toString()); // カレントポジションから引数に渡した文字列の中で一致する文字までの文字列を取得し、カレントポジションを一致した文字まで進める。 // 一致する文字がない場合はカレントポジションから末尾までの文字列が取得し、カレントポジションを末尾まで進める。 Log.d("JSONTokener", "String nextTo(String excluded): " + nextJSJsonTokener.nextTo("1x3")); // カレントポジションと対象文字列を表示する Log.d("JSONTokener", "String toString(): " + nextJSJsonTokener.toString()); // カレントポジションを引数の文字まで進める。 Log.d("JSONTokener", "String nextClean(): " + nextJSJsonTokener.nextClean()); // カレントポジションと対象文字列を表示する Log.d("JSONTokener", "String toString(): " + nextJSJsonTokener.toString()); // カレントポジションを引数の文字まで進める。 Log.d("JSONTokener", "char skipTo(char to): " + nextJSJsonTokener.skipTo('z')); // カレントポジションと対象文字列を表示する Log.d("JSONTokener", "String toString(): " + nextJSJsonTokener.toString()); // カレントポジションを引数の文字列と完全一致するまで進める。 nextJSJsonTokener.skipPast("XY"); // カレントポジションと対象文字列を表示する Log.d("JSONTokener", "String toString(): " + nextJSJsonTokener.toString()); // カレントポジションを引数の文字列と完全一致するまで進める。 Log.d("JSONTokener", "boolean more(): " + nextJSJsonTokener.more()); nextJSJsonTokener.skipPast("Z"); // カレントポジションと対象文字列を表示する Log.d("JSONTokener", "String toString(): " + nextJSJsonTokener.toString()); Log.d("JSONTokener", "boolean more(): " + nextJSJsonTokener.more()); // カレントポジションを一つ戻す。 nextJSJsonTokener.back(); // カレントポジションと対象文字列を表示する Log.d("JSONTokener", "String toString(): " + nextJSJsonTokener.toString()); JSONException myJsonException = nextJSJsonTokener.syntaxError("適当なテキスト"); Log.d("JSONTokener", "JSONException syntaxError(String message): " + myJsonException.getMessage()); String jsonString = "\"int\":200" + "[100,200]" + "{\"int\":200,\"double\":20.5}"; JSONTokener jsonTokener = new JSONTokener(jsonString); // "int"をStringとして取得する Object object = jsonTokener.nextValue(); // ":"はスキップする jsonTokener.next(); // 200をIntegerとして取得する object = jsonTokener.nextValue(); // [100,200]をJSONArrayとして取得する JSONArray jsonArray = (JSONArray) jsonTokener.nextValue(); // {"int":200,"double":20.5}をJSONObjectとして取得する jsonObject = (JSONObject) jsonTokener.nextValue(); Log.d("JSONTokener", "static int dehexchar(char hex): " + JSONTokener.dehexchar('1')); } catch (JSONException e) { e.printStackTrace(); } return jsonObject; } }