Pemprosesan JSON di Java EE 7

1. Gambaran keseluruhan

Artikel ini akan menunjukkan kepada anda cara memproses JSON hanya menggunakan Java EE teras, tanpa menggunakan pergantungan pihak ketiga seperti Jersey atau Jackson. Sebilangan besar semua yang akan kita gunakan disediakan oleh pakej javax.json.

2. Menulis Objek untuk JSON String

Menukar objek Java menjadi JSON String sangat mudah. Anggaplah kita mempunyai kelas Orang sederhana :

public class Person { private String firstName; private String lastName; private Date birthdate; // getters and setters }

Untuk menukar contoh kelas itu ke JSON String , pertama kita perlu membuat contoh JsonObjectBuilder dan menambahkan pasangan harta / nilai menggunakan kaedah tambah () :

JsonObjectBuilder objectBuilder = Json.createObjectBuilder() .add("firstName", person.getFirstName()) .add("lastName", person.getLastName()) .add("birthdate", new SimpleDateFormat("DD/MM/YYYY") .format(person.getBirthdate()));

Perhatikan bahawa kaedah add () mempunyai beberapa versi yang terlalu banyak. Ia dapat menerima sebahagian besar jenis primitif (serta objek berkotak) sebagai parameter kedua.

Setelah selesai menetapkan sifat, kita hanya perlu menulis objek ke dalam String :

JsonObject jsonObject = objectBuilder.build(); String jsonString; try(Writer writer = new StringWriter()) { Json.createWriter(writer).write(jsonObject); jsonString = writer.toString(); }

Dan itu sahaja! String yang dihasilkan akan kelihatan seperti ini:

{"firstName":"Michael","lastName":"Scott","birthdate":"06/15/1978"}

2.1. Menggunakan JsonArrayBuilder untuk Membina Susunan

Sekarang, untuk menambahkan sedikit kerumitan pada contoh kami, mari kita anggap bahawa kelas Orang telah diubah suai untuk menambahkan harta baru yang dipanggil e-mel yang akan mengandungi senarai alamat e-mel:

public class Person { private String firstName; private String lastName; private Date birthdate; private List emails; // getters and setters }

Untuk menambahkan semua nilai dari senarai itu ke JsonObjectBuilder, kami memerlukan bantuan JsonArrayBuilder :

JsonArrayBuilder arrayBuilder = Json.createArrayBuilder(); for(String email : person.getEmails()) { arrayBuilder.add(email); } objectBuilder.add("emails", arrayBuilder);

Perhatikan bahawa kita menggunakan satu lagi versi kaedah tambah () yang memuat objek JsonArrayBuilder sebagai parameter kedua.

Oleh itu, mari lihat objek String for Person yang dihasilkan dengan dua alamat e-mel:

{"firstName":"Michael","lastName":"Scott","birthdate":"06/15/1978", "emails":["[email protected]","[email protected]"]}

2.2. Memformat Output Dengan PRETTY_PRINTING

Oleh itu, kami berjaya menukar objek Java ke JSON String yang sah . Sekarang, sebelum beralih ke bahagian seterusnya, mari kita tambahkan beberapa pemformatan mudah untuk menjadikan output lebih "seperti JSON" dan lebih mudah dibaca.

Dalam contoh sebelumnya, kami membuat JsonWriter menggunakan Json yang berterus terang . createWriter () kaedah statik. Untuk mendapatkan lebih banyak kawalan String yang dihasilkan , kami akan memanfaatkan kemampuan JsonWriterFactory Java 7 untuk membuat penulis dengan konfigurasi tertentu.

Map config = new HashMap(); config.put(JsonGenerator.PRETTY_PRINTING, true); JsonWriterFactory writerFactory = Json.createWriterFactory(config); String jsonString; try(Writer writer = new StringWriter()) { writerFactory.createWriter(writer).write(jsonObject); jsonString = writer.toString(); }

Kodnya mungkin kelihatan sedikit verbose, tetapi sebenarnya tidak banyak.

Pertama, ia membuat contoh JsonWriterFactory menyampaikan peta konfigurasi kepada pembangunnya. Peta mengandungi hanya satu entri yang sesuai dengan harta PRETTY_PRINTING. Kemudian, kami menggunakan contoh kilang untuk membuat penulis, dan bukannya menggunakan Json.createWriter () .

Output baru akan mengandungi jeda baris dan tabulasi khas yang mencirikan JSON String :

{ "firstName":"Michael", "lastName":"Scott", "birthdate":"06/15/1978", "emails":[ "[email protected]", "[email protected]" ] }

3. Membina Objek Java Dari Rentetan

Sekarang mari kita lakukan operasi sebaliknya: ubah JSON String menjadi objek Java.

Bahagian utama proses penukaran berkisar pada JsonObject . Untuk membuat contoh kelas ini, gunakan kaedah statik Json.createReader () diikuti dengan readObject () :

JsonReader reader = Json.createReader(new StringReader(jsonString)); JsonObject jsonObject = reader.readObject();

Kaedah createReader () mengambil InputStream sebagai parameter. Dalam contoh ini, kami menggunakan StringReader, kerana JSON kami terkandung dalam objek String , tetapi kaedah yang sama ini dapat digunakan untuk membaca konten dari file, misalnya, menggunakan FileInputStream .

Dengan adanya contoh JsonObject , kita dapat membaca hartanah menggunakan kaedah getString () dan menetapkan nilai yang diperoleh ke contoh yang baru dibuat dari kelas Person kita :

Person person = new Person(); person.setFirstName(jsonObject.getString("firstName")); person.setLastName(jsonObject.getString("lastName")); person.setBirthdate(dateFormat.parse(jsonObject.getString("birthdate")));

3.1. Menggunakan JsonArray untuk Mendapatkan Nilai Senarai

Kita perlu menggunakan kelas khas, yang dipanggil JsonArray untuk mengekstrak nilai senarai dari JsonObject :

JsonArray emailsJson = jsonObject.getJsonArray("emails"); List emails = new ArrayList(); for (JsonString j : emailsJson.getValuesAs(JsonString.class)) { emails.add(j.getString()); } person.setEmails(emails);

Itu sahaja! Kami telah membuat contoh lengkap Person dari Json String .

4. Meminta Nilai

Sekarang, anggap kita berminat dengan data yang sangat spesifik yang terdapat di dalam JSON String .

Pertimbangkan JSON di bawah yang mewakili pelanggan dari kedai haiwan kesayangan. Katakan bahawa, untuk sebab tertentu, anda perlu mendapatkan nama haiwan kesayangan ketiga dari senarai haiwan peliharaan:

{ "ownerName": "Robert", "pets": [{ "name": "Kitty", "type": "cat" }, { "name": "Rex", "type": "dog" }, { "name": "Jake", "type": "dog" }] }

Mengubah keseluruhan teks menjadi objek Java hanya untuk mendapatkan satu nilai tidak akan sangat berkesan. Oleh itu, mari kita periksa beberapa strategi untuk menanyakan JSON Strings tanpa perlu melalui keseluruhan penukaran.

4.1. Pertanyaan Menggunakan API Model Objek

Menanyakan nilai harta tanah dengan lokasi yang diketahui dalam struktur JSON sangat mudah. Kita boleh menggunakan contoh JsonObject, kelas yang sama yang digunakan dalam contoh sebelumnya:

JsonReader reader = Json.createReader(new StringReader(jsonString)); JsonObject jsonObject = reader.readObject(); String searchResult = jsonObject .getJsonArray("pets") .getJsonObject(2) .getString("name"); 

Hasil tangkapan di sini adalah untuk menavigasi sifat jsonObject menggunakan kaedah urutan get * () yang betul.

In this example, we first get a reference to the “pets” list using getJsonArray(), which returns a list with 3 records. Then, we use getJsonObject() method, which takes an index as a parameter, returning another JsonObject representing the third item in the list. Finally, we use getString() to get the string value we are looking for.

4.2. Querying Using Streaming API

Another way to perform precise queries on a JSON String is using the Streaming API, which has JsonParser as its main class.

JsonParser provides extremely fast, read-only, forward access to JS, with the drawback of being somewhat more complicated than the Object Model:

JsonParser jsonParser = Json.createParser(new StringReader(jsonString)); int count = 0; String result = null; while(jsonParser.hasNext()) { Event e = jsonParser.next(); if (e == Event.KEY_NAME) { if(jsonParser.getString().equals("name")) { jsonParser.next(); if(++count == 3) { result = jsonParser.getString(); break; } } } }

This example delivers the same result as the previous one. It returns the name from the third pet in the pets list.

Once a JsonParser is created using Json.createParser(), we need to use an iterator (hence the “forward access” nature of the JsonParser) to navigate through the JSON tokens until we get to the property (or properties) we are looking for.

Every time we step through the iterator we move to the next token of the JSON data. So we have to be careful to check if the current token has the expected type. This is done by checking the Event returned by the next() call.

There are many different types of tokens. In this example, we are interested in the KEY_NAME types, which represent the name of a property (e.g. “ownerName”, “pets”, “name”, “type”). Once we stepped through a KEY_NAME token with a value of “name” for the third time, we know that the next token will contain a string value representing the name of the third pet from the list.

This is definitely harder than using the Object Model API, especially for more complicated JSON structures. The choice between one or the other, as always, depends on the specific scenario you will be dealing with.

5. Conclusion

We have covered a lot of ground on the Java EE JSON Processing API with a couple of simple examples. To learn other cool stuff about JSON processing, check our series of Jackson articles.

Periksa kod sumber kelas yang digunakan dalam artikel ini, serta beberapa ujian unit, di repositori GitHub kami.