JSONパーサー「UtlJson」
2010/12/27 ページ作成
2011/09/05 最終更新
クロノス・クラウン合同会社
柳井政和
HP:http://crocro.com/
Twitter:http://twitter.com/ruten
2011/09/05 最終更新
クロノス・クラウン合同会社
柳井政和
HP:http://crocro.com/
Twitter:http://twitter.com/ruten
はじめに
200行程度で動作する、JAVA製のJSONパーサー「UtlJson」です。
車輪の再発明っぽいものですが、作成する必要が生じたので、簡単なプログラムを書きました。短いプログラムですので、自由に改造して、ご利用いただければと思います。
作成の背景
拙作ゲームアプリ「Army & Maiden」の開発に伴い、AndroidとPCコンパチで動作するゲーム開発ライブラリを作成しました。
□Army & Maiden PC版、Android版、アプレット版 まとめページ
そのため、PCとAndroidで、共通で動くJSONパースライブラリが必要になりましたので自作しました(既存のライブラリを使うという手もあったのですが、ProGuardに引っ掛かってしまい、上手く動作しませんでした)。
200行ほどの短いプログラムですので、全文をそのまま掲載します。自由にコピペしてご利用していただいて結構です。あまり検証はしていないので、バグなどがあるかもしれません。バグを修正された方はフィードバックをいただければと思います。反映したいと思います。
(2011/09/05 バグの報告を受けてバージョンアップ)
それでは以下、ソースコードと使い方を掲載します。
JSONパース用クラスのソースコード
package com.crocro.wrp.utl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
public class UtlJson {
//------------------------------------------------------------
//-- メンバー変数
//------------------------------------------------------------
// 解析
private String mSrcStr;
private int mPos; // 解析位置
private int mLen; // 文字列長
// デバッグ
private static String NST_TB = " "; // ネスト用タブ
//------------------------------------------------------------
//-- prs | JSONのパース
//------------------------------------------------------------
/*
* JSONのパース。なんちゃってパースなので、正確な処理は行っていないので注意。
* 配列はArrayList、ハッシュはHashMapで作成する。
* @param srcStr 元文字列
* @return 解析後のオブジェクト
*/
public Object prs(String srcStr) {
// エラー対策
if (srcStr == null || srcStr.length() == 0) return null;
// 変数の初期化
Object resObj = null;
mSrcStr = srcStr;
mPos = 0;
mLen = srcStr.length();
// 括弧の探索
for (; mPos < mLen; mPos ++) {
char c = srcStr.charAt(mPos);
if (c == '[') {
// 配列である
resObj = prsArr();
} else
if (c == '{') {
// ハッシュである
resObj = prsHsh();
}
}
// 戻り値を戻して終了
return resObj;
}
//------------------------------------------------------------
//-- prsArr | 配列のパース
//------------------------------------------------------------
/*
* 配列のパース。
* @return 解析後の配列
*/
public Object prsArr() {
// 変数の初期化
ArrayList<Object> al = new ArrayList<Object>();
// 内部の探索
for (mPos ++; mPos < mLen; mPos ++) {
char c = mSrcStr.charAt(mPos);
if (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
continue;
} else
if (c == ']') {
// 配列の終了
break;
} else
if (c == '[') {
// 配列である
Object obj = prsArr();
al.add(obj);
nowKey = "";
flgKey = !flgKey;
} else
if (c == '{') {
// ハッシュである
Object obj = prsHsh();
al.add(obj);
nowKey = "";
flgKey = !flgKey;
} else
if (c == ',') {
// カンマである
continue;
} else
if (c == '"' || c == '\'') {
// 括弧付き文字列である
String str = prsStrDsh();
al.add(str);
} else {
// 文字列である
String str = prsStr();
al.add(str);
}
}
// 戻り値を戻して終了
return al;
}
//------------------------------------------------------------
//-- prsStr | 文字列のパース
//------------------------------------------------------------
/*
* 文字列のパース。
* @return 解析後の配列
*/
public String prsStr() {
// 変数の初期化
int strtPos = mPos;
// 内部の探索
for (mPos ++; mPos < mLen; mPos ++) {
char c = mSrcStr.charAt(mPos);
if (c == ',' || c == ':' || c == '}' || c == ']') {
mPos --;
break;
}
}
// 戻り値を戻して終了
if (mPos >= mLen) return mSrcStr.substring(strtPos); // エラー対策、通常は来ない
return mSrcStr.substring(strtPos, mPos + 1);
}
//------------------------------------------------------------
//-- prsStrDsh | ダッシュ付き文字列のパース
//------------------------------------------------------------
/*
* ダッシュ付き文字列のパース。
* @return 解析後の配列
*/
public String prsStrDsh() {
// 変数の初期化
int strtPos = mPos;
char strtChr = mSrcStr.charAt(mPos);
boolean wDsh = (strtChr == '"') ? true : false;
boolean sDsh = (strtChr == '\'') ? true : false;
// 内部の探索
for (mPos ++; mPos < mLen; mPos ++) {
char c = mSrcStr.charAt(mPos);
if (wDsh && c == '"' && mSrcStr.charAt(mPos - 1) != '\') break;
if (sDsh && c == '\'' && mSrcStr.charAt(mPos - 1) != '\') break;
}
// 戻り値を戻して終了
if (mPos >= mLen) return mSrcStr.substring(strtPos + 1); // エラー対策、通常は来ない
return mSrcStr.substring(strtPos + 1, mPos);
}
//------------------------------------------------------------
//-- prsHsh | ハッシュのパース
//------------------------------------------------------------
/*
* ハッシュのパース。
* @return 解析後の配列
*/
public Object prsHsh() {
// 変数の初期化
HashMap<String, Object> hsh = new HashMap<String, Object>();
String nowKey = "";
boolean flgKey = true;
// 内部の探索
for (mPos ++; mPos < mLen; mPos ++) {
char c = mSrcStr.charAt(mPos);
if (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
continue;
} else
if (c == '}') {
// ハッシュの終了
break;
} else
if (c == '[') {
// 配列である
Object obj = prsArr();
hsh.put(nowKey, obj);
} else
if (c == '{') {
// ハッシュである
Object obj = prsHsh();
hsh.put(nowKey, obj);
} else
if (c == ':' || c == ',') {
// ハッシュの区切りか、カンマである
continue;
} else
if (c == '"' || c == '\'') {
// 括弧付き文字列である
String str = prsStrDsh();
if (! flgKey) {
hsh.put(nowKey, str);
nowKey = "";
} else {
nowKey = str;
}
flgKey = !flgKey;
} else {
// 文字列である
String str = prsStr();
if (! flgKey) {
hsh.put(nowKey, str);
nowKey = "";
} else {
nowKey = str;
}
flgKey = !flgKey;
}
}
// 戻り値を戻して終了
return hsh;
}
//------------------------------------------------------------
//-- dump | ダンプ出力
//------------------------------------------------------------
/*
* 解析後のオブジェクトを、文字列としてダンプ出力する。
* @param srcObj 元オブジェクト。
*/
public static void dump(Object srcObj) {
dump(srcObj, 0);
}
private static void dump(Object srcObj, int nst) {
// ネスト文字列
String nstStr = "";
for (int i = 0; i < nst; i ++) nstStr += NST_TB;
if (srcObj.getClass().getSimpleName().equals("ArrayList")) {
// 配列
System.out.println(nstStr + "<Array>");
ArrayList<?> al = (ArrayList<?>)srcObj;
for (int i = 0; i < al.size(); i ++) {
Object obj = al.get(i);
if (obj.getClass().getSimpleName().equals("String")) {
System.out.println(nstStr + NST_TB + obj.toString()); // 文字列
} else {
dump(obj, nst + 1); // その他
}
}
System.out.println(nstStr + "</Array>");
} else
if (srcObj.getClass().getSimpleName().equals("HashMap")) {
// ハッシュ
System.out.println(nstStr + "<Hash>");
HashMap<?, ?> hsh = (HashMap<?, ?>)srcObj;
Iterator<?> it = hsh.keySet().iterator();
while (it.hasNext()) {
String key = (String)it.next();
Object obj = hsh.get(key);
if (obj.getClass().getSimpleName().equals("String")) {
System.out.println(nstStr + NST_TB + "[" + key + "] : "
+ obj.toString()); // 文字列
} else {
System.out.println(nstStr + NST_TB + "[" + key + "] : ");
dump(obj, nst + 2); // その他
}
}
System.out.println(nstStr + "</Hash>");
}
}
}
使用例
以下、読み込むJSON文字列です。
[{cmnd:"setVar", key:"mvYMes",val:"-120"}
,{cmnd:"setVar", key:"mvYMesOut",val:"-150"}
,{cmnd:"setVar", key:"mvYNm", val:"120"}
,{cmnd:"setBck", pth:"gm/bck_grd.png", w:"fit", h:"img", bsX:"c", bsY:"c"}
,{cmnd:"rstImg"}
,{cmnd:"setMes", mes:"Stage 6\nBonus Stage 1\nStart!"}
,{cmnd:"wait"}
]
以下、プログラムです。「scrptStr」は、ファイルなどから読み取った、上記の文字列です。
// UtlJsonの初期化
UtlJson jsn = new UtlJson();
// 元のJSONが配列なので、配列として取得
ArrayList> jsnArr = (ArrayList>)jsn.prs(scrptStr);
// ダンプ出力
UtlJson.dump(jsnArr);
// 配列の要素を処理
for (int i = 0; i < jsnArr.size(); i ++) {
// ハッシュを取り出し
HashMap, ?> jsnHsh = (HashMap, ?>)jsnArr.get(i);
}
以下、ダンプ出力結果です。
<Array>
<Hash>
[val] : -120
[cmnd] : setVar
[key] : mvYMes
</Hash>
<Hash>
[val] : -150
[cmnd] : setVar
[key] : mvYMesOut
</Hash>
<Hash>
[val] : 120
[cmnd] : setVar
[key] : mvYNm
</Hash>
<Hash>
[bsY] : c
[w] : fit
[pth] : gm/bck_grd.png
[cmnd] : setBck
[h] : img
[bsX] : c
</Hash>
<Hash>
[cmnd] : rstImg
</Hash>
<Hash>
[mes] : Stage 6\nBonus Stage 1\nStart!
[cmnd] : setMes
</Hash>
<Hash>
[cmnd] : wait
</Hash>
</Array>







