1. Gambaran keseluruhan
Tutorial ini memfokuskan pada pemahaman kelas Jackson ObjectMapper dan cara menyusun objek Java ke dalam JSON dan mendesialisasikan rentetan JSON ke dalam objek Java.
Untuk memahami lebih lanjut mengenai perpustakaan Jackson secara umum, Jackson Tutorial adalah tempat yang baik untuk bermula.
2. Kebergantungan
Mari kita tambahkan kebergantungan berikut ke pom.xml :
com.fasterxml.jackson.core jackson-databind 2.11.1
Pergantungan ini juga akan menambahkan perpustakaan berikut secara sementara ke classpath:
- anotasi jackson
- inti jackson
Sentiasa gunakan versi terbaru dari repositori pusat Maven untuk jackson-databaseind .
3. Membaca dan Menulis Menggunakan ObjectMapper
Mari mulakan dengan operasi asas membaca dan menulis.
API readValue yang mudah dari ObjectMapper adalah titik masuk yang baik. Kita dapat menggunakannya untuk mengurai atau mendesialisasikan konten JSON ke dalam objek Java.
Juga, di sisi penulisan, kita dapat menggunakan API writeValue untuk menyusun objek Java sebagai output JSON.
Kami akan menggunakan kelas Kereta berikut dengan dua bidang sebagai objek untuk membuat siri atau deserialisasi sepanjang artikel ini:
public class Car { private String color; private String type; // standard getters setters }
3.1. Objek Java ke JSON
Mari kita lihat contoh pertama untuk menyusun objek Java ke dalam JSON menggunakan kaedah writeValue dari kelas ObjectMapper :
ObjectMapper objectMapper = new ObjectMapper(); Car car = new Car("yellow", "renault"); objectMapper.writeValue(new File("target/car.json"), car);
Output dari perkara di atas adalah:
{"color":"yellow","type":"renault"}
Kaedah writeValueAsString dan writeValueAsBytes dari kelas ObjectMapper menghasilkan JSON dari objek Java dan mengembalikan JSON yang dihasilkan sebagai rentetan atau sebagai array byte:
String carAsString = objectMapper.writeValueAsString(car);
3.2. JSON ke Objek Java
Di bawah ini adalah contoh mudah untuk menukar JSON String ke objek Java menggunakan kelas ObjectMapper :
String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }"; Car car = objectMapper.readValue(json, Car.class);
Fungsi readValue () juga menerima bentuk input lain, seperti fail yang mengandungi rentetan JSON:
Car car = objectMapper.readValue(new File("src/test/resources/json_car.json"), Car.class);
atau URL:
Car car = objectMapper.readValue(new URL("file:src/test/resources/json_car.json"), Car.class);
3.3. JSON ke Jackson JsonNode
Sebagai alternatif, JSON dapat diuraikan ke objek JsonNode dan digunakan untuk mengambil data dari simpul tertentu:
String json = "{ \"color\" : \"Black\", \"type\" : \"FIAT\" }"; JsonNode jsonNode = objectMapper.readTree(json); String color = jsonNode.get("color").asText(); // Output: color -> Black
3.4. Membuat Senarai Java Dari Rentetan JSON Array
Kita dapat menguraikan JSON dalam bentuk array ke dalam senarai objek Java menggunakan TypeReference :
String jsonCarArray = "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]"; List listCar = objectMapper.readValue(jsonCarArray, new TypeReference
(){});
3.5. Membuat Peta Java Dari JSON String
Begitu juga, kita dapat menguraikan JSON ke dalam Peta Java :
String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }"; Map map = objectMapper.readValue(json, new TypeReference
4. Ciri Lanjutan
Salah satu kekuatan terbesar perpustakaan Jackson adalah proses serialisasi dan deserialisasi yang sangat disesuaikan.
Pada bahagian ini, kita akan melalui beberapa ciri lanjutan di mana input atau output JSON tindak balas boleh berbeza dari objek yang menghasilkan atau memakan respons.
4.1. Mengkonfigurasi Ciri Serialisasi atau Deserialisasi
Semasa menukar objek JSON ke kelas Java, sekiranya rentetan JSON memiliki beberapa bidang baru, proses lalai akan menghasilkan pengecualian:
String jsonString = "{ \"color\" : \"Black\", \"type\" : \"Fiat\", \"year\" : \"1970\" }";
Rentetan JSON dalam contoh di atas dalam proses mengurai lalai ke objek Java untuk Kelas Kereta akan menghasilkan pengecualian UnrecognizedPropertyException .
Melalui kaedah konfigurasi , kita dapat memperluas proses lalai untuk mengabaikan bidang baru :
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); Car car = objectMapper.readValue(jsonString, Car.class); JsonNode jsonNodeRoot = objectMapper.readTree(jsonString); JsonNode jsonNodeYear = jsonNodeRoot.get("year"); String year = jsonNodeYear.asText();
Pilihan lain adalah berdasarkan FAIL_ON_NULL_FOR_PRIMITIVES , yang menentukan apakah nilai null untuk nilai primitif dibenarkan:
objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);
Begitu juga, FAIL_ON_NUMBERS_FOR_ENUM mengawal jika nilai enum dibiarkan bersiri / deserialisasi sebagai nombor:
objectMapper.configure(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS, false);
Anda boleh mendapatkan senarai lengkap ciri siri dan deserialisasi di laman rasmi.
4.2. Membuat Serializer Custom atau Deserializer
Another essential feature of the ObjectMapper class is the ability to register a custom serializer and deserializer.
Custom serializers and deserializers are very useful in situations where the input or the output JSON response is different in structure than the Java class into which it must be serialized or deserialized.
Below is an example of a custom JSON serializer:
public class CustomCarSerializer extends StdSerializer { public CustomCarSerializer() { this(null); } public CustomCarSerializer(Class t) { super(t); } @Override public void serialize( Car car, JsonGenerator jsonGenerator, SerializerProvider serializer) { jsonGenerator.writeStartObject(); jsonGenerator.writeStringField("car_brand", car.getType()); jsonGenerator.writeEndObject(); } }
This custom serializer can be invoked like this:
ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("CustomCarSerializer", new Version(1, 0, 0, null, null, null)); module.addSerializer(Car.class, new CustomCarSerializer()); mapper.registerModule(module); Car car = new Car("yellow", "renault"); String carJson = mapper.writeValueAsString(car);
Here's what the Car looks like (as JSON output) on the client side:
var carJson = {"car_brand":"renault"}
And here's an example of a custom JSON deserializer:
public class CustomCarDeserializer extends StdDeserializer { public CustomCarDeserializer() { this(null); } public CustomCarDeserializer(Class vc) { super(vc); } @Override public Car deserialize(JsonParser parser, DeserializationContext deserializer) { Car car = new Car(); ObjectCodec codec = parser.getCodec(); JsonNode node = codec.readTree(parser); // try catch block JsonNode colorNode = node.get("color"); String color = colorNode.asText(); car.setColor(color); return car; } }
This custom deserializer can be invoked in this way:
String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }"; ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("CustomCarDeserializer", new Version(1, 0, 0, null, null, null)); module.addDeserializer(Car.class, new CustomCarDeserializer()); mapper.registerModule(module); Car car = mapper.readValue(json, Car.class);
4.3. Handling Date Formats
The default serialization of java.util.Date produces a number, i.e., epoch timestamp (number of milliseconds since January 1, 1970, UTC). But this is not very human readable and requires further conversion to be displayed in a human-readable format.
Let's wrap the Car instance we used so far inside the Request class with the datePurchased property:
public class Request { private Car car; private Date datePurchased; // standard getters setters }
To control the String format of a date and set it to, e.g., yyyy-MM-dd HH:mm a z, consider the following snippet:
ObjectMapper objectMapper = new ObjectMapper(); DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm a z"); objectMapper.setDateFormat(df); String carAsString = objectMapper.writeValueAsString(request); // output: {"car":{"color":"yellow","type":"renault"},"datePurchased":"2016-07-03 11:43 AM CEST"}
To learn more about serializing dates with Jackson, read our more in-depth write-up.
4.4. Handling Collections
Satu lagi ciri kecil tetapi berguna yang tersedia melalui kelas DeserializationFeature adalah kemampuan untuk menghasilkan jenis koleksi yang kita mahukan daripada respons JSON Array.
Sebagai contoh, kita dapat menghasilkan hasilnya sebagai tatasusunan:
String jsonCarArray = "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]"; ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true); Car[] cars = objectMapper.readValue(jsonCarArray, Car[].class); // print cars
Atau sebagai Senarai :
String jsonCarArray = "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]"; ObjectMapper objectMapper = new ObjectMapper(); List listCar = objectMapper.readValue(jsonCarArray, new TypeReference
(){}); // print cars
Maklumat lebih lanjut mengenai pengendalian koleksi dengan Jackson terdapat di sini.
5. Kesimpulan
Jackson adalah perpustakaan siri / deserialisasi JSON yang mantap dan matang untuk Java. The ObjectMapper API menyediakan cara yang mudah untuk menghurai dan menjana JSON objek tindak balas dengan banyak fleksibiliti. Artikel ini membincangkan ciri-ciri utama yang menjadikan perpustakaan begitu popular.
Kod sumber yang menyertai artikel boleh didapati di GitHub.