Java Language
JavaのJSON
サーチ…
前書き
JSON(JavaScript Object Notation)は、人間や機械が読み書きするのに簡単な、軽量でテキストベースの言語に依存しないデータ交換形式です。 JSONは、オブジェクトと配列という2つの構造化型を表現できます。 JSONは、Ajaxアプリケーション、設定、データベース、およびRESTful Webサービスでよく使用されます。 JSON処理用のJava APIは、JSONを解析、生成、変換、および照会するための移植可能なAPIを提供します。
備考
この例では、 Google Gsonライブラリ、Jackson Object Mapperなどのさまざまなライブラリを使用して、JavaでJSONを解析および作成する方法を中心に説明します。
他のライブラリを使用した例は、ここで見つけることができます: JSONをJavaで解析する方法
データをJSON形式でエンコードする
JSONObject
を作成してデータを格納する必要がある場合は、次の例を検討してください。
// Create a new javax.json.JSONObject instance.
JSONObject first = new JSONObject();
first.put("foo", "bar");
first.put("temperature", 21.5);
first.put("year", 2016);
// Add a second object.
JSONObject second = new JSONObject();
second.put("Hello", "world");
first.put("message", second);
// Create a new JSONArray with some values
JSONArray someMonths = new JSONArray(new String[] { "January", "February" });
someMonths.put("March");
// Add another month as the fifth element, leaving the 4th element unset.
someMonths.put(4, "May");
// Add the array to our object
object.put("months", someMonths);
// Encode
String json = object.toString();
// An exercise for the reader: Add pretty-printing!
/* {
"foo":"bar",
"temperature":21.5,
"year":2016,
"message":{"Hello":"world"},
"months":["January","February","March",null,"May"]
}
*/
JSONデータのデコード
JSONObject
からデータを取得する必要がある場合は、次の例を検討してください。
String json = "{\"foo\":\"bar\",\"temperature\":21.5,\"year\":2016,\"message\":{\"Hello\":\"world\"},\"months\":[\"January\",\"February\",\"March\",null,\"May\"]}";
// Decode the JSON-encoded string
JSONObject object = new JSONObject(json);
// Retrieve some values
String foo = object.getString("foo");
double temperature = object.getDouble("temperature");
int year = object.getInt("year");
// Retrieve another object
JSONObject secondary = object.getJSONObject("message");
String world = secondary.getString("Hello");
// Retrieve an array
JSONArray someMonths = object.getJSONArray("months");
// Get some values from the array
int nMonths = someMonths.length();
String february = someMonths.getString(1);
optXXXとgetXXXのメソッド
JSONObject
とJSONArray
は、取得しようとしている値が存在しないか、別の型の可能性を扱う際に非常に便利なメソッドがいくつかあります。
JSONObject obj = new JSONObject();
obj.putString("foo", "bar");
// For existing properties of the correct type, there is no difference
obj.getString("foo"); // returns "bar"
obj.optString("foo"); // returns "bar"
obj.optString("foo", "tux"); // returns "bar"
// However, if a value cannot be coerced to the required type, the behavior differs
obj.getInt("foo"); // throws JSONException
obj.optInt("foo"); // returns 0
obj.optInt("foo", 123); // returns 123
// Same if a property does not exist
obj.getString("undefined"); // throws JSONException
obj.optString("undefined"); // returns ""
obj.optString("undefined", "tux"); // returns "tux"
同じルールが適用されますにgetXXX
/ optXXX
の方法JSONArray
。
JSONへのオブジェクト(Gsonライブラリ)
Person
name
クラスがあると仮定します。
private class Person {
public String name;
public Person(String name) {
this.name = name;
}
}
コード:
Gson g = new Gson();
Person person = new Person("John");
System.out.println(g.toJson(person)); // {"name":"John"}
もちろん、 Gsonの瓶はクラスパス上になければなりません。
JSON To Object(Gsonライブラリ)
Person
name
クラスがあると仮定します。
private class Person {
public String name;
public Person(String name) {
this.name = name;
}
}
コード:
Gson gson = new Gson();
String json = "{\"name\": \"John\"}";
Person person = gson.fromJson(json, Person.class);
System.out.println(person.name); //John
クラスパスにgsonライブラリが必要です。
JSONから単一要素を抽出する
String json = "{\"name\": \"John\", \"age\":21}";
JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject();
System.out.println(jsonObject.get("name").getAsString()); //John
System.out.println(jsonObject.get("age").getAsInt()); //21
Jackson Object Mapperの使用
ポホモデル
public class Model {
private String firstName;
private String lastName;
private int age;
/* Getters and setters not shown for brevity */
}
例:オブジェクトへの文字列
Model outputObject = objectMapper.readValue(
"{\"firstName\":\"John\",\"lastName\":\"Doe\",\"age\":23}",
Model.class);
System.out.println(outputObject.getFirstName());
//result: John
例:Object to String
String jsonString = objectMapper.writeValueAsString(inputObject));
//result: {"firstName":"John","lastName":"Doe","age":23}
詳細
必要なインポートステートメント:
import com.fasterxml.jackson.databind.ObjectMapper;
ObjectMapper
インスタンス
//creating one
ObjectMapper objectMapper = new ObjectMapper();
-
ObjectMapper
はスレッドセーフです - 推奨:共有された静的インスタンスを持つ
デシリアライゼーション:
<T> T readValue(String content, Class<T> valueType)
-
valueType
を指定する必要があります。戻り値はこの型になります - スロー
-
IOException
- 低レベルのI / O問題の場合 -
JsonParseException
- 基本となる入力に無効なコンテンツが含まれている場合 -
JsonMappingException
- 入力JSON構造体がオブジェクト構造体と一致しない場合
-
使用例(jsonStringは入力文字列です):
Model fromJson = objectMapper.readValue(jsonString, Model.class);
シリアライズの方法:
String writeValueAsString(オブジェクト値)
- スロー
-
JsonProcessingException
エラーが発生した場合 - 注意:バージョン2.1より前のリリースでは、IOExceptionがスローされました。 2.1はそれを削除しました。
-
JSON反復
JSONObject
プロパティを繰り返し処理する
JSONObject obj = new JSONObject("{\"isMarried\":\"true\", \"name\":\"Nikita\", \"age\":\"30\"}");
Iterator<String> keys = obj.keys();//all keys: isMarried, name & age
while (keys.hasNext()) { //as long as there is another key
String key = keys.next(); //get next key
Object value = obj.get(key); //get next value by key
System.out.println(key + " : " + value);//print key : value
}
JSONArray
値をJSONArray
する
JSONArray arr = new JSONArray(); //Initialize an empty array
//push (append) some values in:
arr.put("Stack");
arr.put("Over");
arr.put("Flow");
for (int i = 0; i < arr.length(); i++) {//iterate over all values
Object value = arr.get(i); //get value
System.out.println(value); //print each value
}
JSON Builder - 連鎖メソッド
JSONObject
とJSONArray
しながらメソッド連鎖を使用できます。
JSONObjectの例
JSONObject obj = new JSONObject();//Initialize an empty JSON object
//Before: {}
obj.put("name","Nikita").put("age","30").put("isMarried","true");
//After: {"name":"Nikita","age":30,"isMarried":true}
JSONArray
JSONArray arr = new JSONArray();//Initialize an empty array
//Before: []
arr.put("Stack").put("Over").put("Flow");
//After: ["Stack","Over","Flow"]
JSONObject.NULL
null
値を持つプロパティを追加する必要がある場合は、事前定義された静的なJSONObject.NULL
を使用し、標準のJava null
参照は使用しないでください。
JSONObject.NULL
は、値が空のプロパティを明示的に定義するために使用されるセンチネル値です。
JSONObject obj = new JSONObject();
obj.put("some", JSONObject.NULL); //Creates: {"some":null}
System.out.println(obj.get("some"));//prints: null
注意
JSONObject.NULL.equals(null); //returns true
Java.equals()
契約の明確な違反はどれですか:
null以外の参照値xの場合、x.equals(null)はfalseを返す必要があります。
JsonArrayからJavaリストへ(Gsonライブラリ)
ここでは、Java ArrayList
に変換したい単純なJsonArrayを示します:
{
"list": [
"Test_String_1",
"Test_String_2"
]
}
次に、 JsonArray
'list'を、対応するJava ArrayList
を返す次のメソッドに渡します。
public ArrayList<String> getListString(String jsonList){
Type listType = new TypeToken<List<String>>() {}.getType();
//make sure the name 'list' matches the name of 'JsonArray' in your 'Json'.
ArrayList<String> list = new Gson().fromJson(jsonList, listType);
return list;
}
POM.xml
ファイルに次のMaven依存関係を追加する必要があります。
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.7</version>
</dependency>
または、クラスパスにcom.google.code.gson:gson:jar:<version>
があるはずです。
Jacksonを使用してJSONコレクションをオブジェクトコレクションにデシリアライズする
あなたがpojoクラスPerson
を持っているとします
public class Person {
public String name;
public Person(String name) {
this.name = name;
}
}
JSON配列やPersonオブジェクトのマップに解析したいとします。型の削除のため、実行時にList<Person>
およびMap<String, Person>
クラスを直接作成することはできません(したがって、それらを使用してJSONを逆シリアル化します) 。この制限を克服するために、 TypeReference
TypeFactory
とTypeReference
2つのアプローチを提供します。
TypeFactory
ここで取り上げるアプローチは、ファクトリ(およびその静的ユーティリティ関数)を使用して型を構築することです。パラメータは、使用するコレクション(リスト、セットなど)と、そのコレクションに格納するクラスです。
型参照
型参照のアプローチは、あなたの入力を少しだけ節約し、よりきれいに見えるので簡単です。 TypeReferenceは、タイプパラメータを受け取ります。ここで、目的のタイプのList<Person>
を渡します。このTypeReferenceオブジェクトをインスタンス化し、それを型コンテナとして使用するだけです。
次にJSONを実際にJavaオブジェクトに逆シリアル化する方法を見てみましょう。 JSONが配列として書式設定されている場合は、リストとして逆シリアル化できます。より複雑なネストされた構造がある場合は、マップにデシリアライズする必要があります。両方の例を見てみましょう。
JSON配列のデシリアライズ
String jsonString = "[{\"name\": \"Alice\"}, {\"name\": \"Bob\"}]"
タイプファクトリーアプローチ
CollectionType listType =
factory.constructCollectionType(List.class, Person.class);
List<Preson> list = mapper.readValue(jsonString, listType);
タイプ参照アプローチ
TypeReference<Person> listType = new TypeReference<List<Person>>() {};
List<Person> list = mapper.readValue(jsonString, listType);
JSONマップを逆シリアル化する
String jsonString = "{\"0\": {\"name\": \"Alice\"}, \"1\": {\"name\": \"Bob\"}}"
タイプファクトリーアプローチ
CollectionType mapType =
factory.constructMapLikeType(Map.class, String.class, Person.class);
List<Person> list = mapper.readValue(jsonString, mapType);
タイプ参照アプローチ
TypeReference<Person> mapType = new TypeReference<Map<String, Person>>() {};
Map<String, Person> list = mapper.readValue(jsonString, mapType);
詳細
使用されるインポートステートメント:
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
使用されるインスタンス:
ObjectMapper mapper = new ObjectMapper();
TypeFactory factory = mapper.getTypeFactory();
注意
TypeReference
アプローチは良く見えるかもしれませんが、いくつかの欠点があります:
-
TypeReference
は匿名クラスを使用してインスタンス化する必要があります - あなたは一般的な明示性を提供するべきです
そうしないとジェネリック型引数が失われ、デシリアライゼーションに失敗する可能性があります。