やりたいこと
String jsonString = "{\"Apple\":{"
+ "\"cost\":\"0\"},"
+ "\"Pen\":{"
+ "\"cost\":\"0\"}}";
やりたいのは以下の2点です。
- 上記のJson文字列の
"0"
にあたる部分を編集したい。 - 新たなキー
"ApplePen"
を追加したい。
今回は以下の代表的(?)なJsonを操作するためのライブラリを使ってみます。
- Gson
- Jackson
実行環境
Android Studio: 3.4.1
gradle: 5.1.1
ライブラリ追加
追加するライブラリをbuild.gradleのdependenciesブロックに記述します。
dependencies {
...
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.8'
implementation 'org.glassfish:javax.json:1.1.4'
}
Gson
作成したメソッド(editJson)でJson文字列を
Map<String, MAP<String, String>>
という形に置き換え(Gson.fromJson)、目的のキーと値を代入しています。
代入後、Mapを再びJson文字列に変換しています(Gson.toJson)。
本題と逸れますが、
[Json => 他のクラス] の変換を「Deserialization」、
[他のクラス => Json] の変換を「Serialization」と呼ぶんですね。
import com.google.gson.Gson;
...
public class GsonExample {
String jsonString = "{\"Apple\":{" +
"\"cost\":\"0\"}," +
"\"Pen\":{" +
"\"cost\":\"0\"}}";
public void main() {
editJson("Apple", "100");
/*
{
"Apple": {
"cost": "100"
},
"Pen": {"
"cost": "0"
}
}"
*/
editJson("ApplePen", "");
/*
{
"Apple": {
"cost": "100"
},
"Pen": {"
"cost": "0"
}
"ApplePen": {"
"cost": "0"
}
}"
*/
}
private void editJson(String key, String str) {
if (str.isEmpty()) str = "0";
Map<String, String> innerMap = new HashMap<>();
innerMap.put("cost", str);
Gson gson = new Gson();
// Json文字列をMapに変換
Map<String, Map<String,String>> jsonMap = gson.fromJson(jsonString, Map.class);
jsonMap.put(key, innerMap);
// Mapを再びJson文字列に変換
jsonString = gson.toJson(jsonMap);
}
}
Jackson
Gsonの時とほぼ同様に置き換え処理を行なっています。
JacksonではObjectMapper
のメソッドを介してJsonを変換します。
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
...
public class JacksonExample {
// main()は省略
private void editJson(String str, String key) {
if (str.isEmpty()) str = "0";
Map<String, Object> map = null;
Map<String, String> innerMap = new HashMap<>();
innerMap.put("cost", str);
ObjectMapper mapper = new ObjectMapper();
try {
// Json文字列をMapに変換
map = mapper.readValue(json,
new TypeReference<Map<String, Object>>() {});
} catch (IOException e) {
e.printStackTrace();
}
map.put(key, innerMap);
try {
// Mapを再びJson文字列に変換
json = mapper.writeValueAsString(map);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
}
javax.jsonについて
javax.jsonライブラリでも同様の実装ができるか試してみましたが、行き詰まってしまいました。
- Json文字列をMapに変換できなそう?
- JsonObjectに対して書き換え処理ができない。(UnsupportedOperationException発生)
感想
- Gsonは使いやすい。
- TypeReferenceがなにもわからない。
20.09.27追記 (org.json.JSONObjectについて)
JsonをMapに変換して値を追加するだけならorg.json.JSONObject
でもいけることに気づきました。
import org.json.JSONException;
import org.json.JSONObject;
...
public class JSONExample {
// main()は省略
private void editJson(String str, String key) {
if (str.isEmpty()) str = "0";
Map<String, String> innerMap = new HashMap<>();
innerMap.put("cost", str);
try {
JSONObject jsonObject = new JSONObject(json);
jsonObject.put(key, new JSONObject(innerMap));
json = jsonObject.toString();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
参考文献
以下の記事を参考にさせていただきました。
- Gson, Jacksonの使用方法について
- Gson
- Jackson
- javax.json