Pendahuluan tentang Jackson ObjectMapper

1. Ikhtisar

Tutorial ini berfokus pada pemahaman kelas Jackson ObjectMapper dan cara membuat serial objek Java ke dalam JSON dan deserialisasi string JSON ke objek Java.

Untuk memahami lebih lanjut tentang perpustakaan Jackson secara umum, Tutorial Jackson adalah tempat yang baik untuk memulai.

2. Dependensi

Pertama-tama, tambahkan dependensi berikut ke pom.xml :

 com.fasterxml.jackson.core jackson-databind 2.11.1  

Ketergantungan ini juga secara transitif akan menambahkan pustaka berikut ke classpath:

  1. jackson-annotations
  2. jackson-core

Selalu gunakan versi terbaru dari repositori pusat Maven untuk jackson-databind .

3. Membaca dan Menulis Menggunakan ObjectMapper

Mari kita mulai dengan operasi baca dan tulis dasar.

API readValue sederhana dari ObjectMapper adalah titik masuk yang baik. Kita bisa menggunakannya untuk mem-parsing atau deserialisasi konten JSON menjadi objek Java.

Selain itu, di sisi penulisan, kita dapat menggunakan writeValue API untuk membuat serial objek Java apa pun sebagai output JSON.

Kami akan menggunakan kelas Mobil berikut dengan dua bidang sebagai objek untuk membuat serial atau deserialisasi di seluruh 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 dari membuat serial objek Java ke JSON menggunakan metode writeValue kelas ObjectMapper :

ObjectMapper objectMapper = new ObjectMapper(); Car car = new Car("yellow", "renault"); objectMapper.writeValue(new File("target/car.json"), car); 

Output dari file di atas akan menjadi:

{"color":"yellow","type":"renault"} 

Metode writeValueAsString dan writeValueAsBytes dari ObjectMapper kelas menghasilkan JSON dari objek Java dan mengembalikan dihasilkan JSON sebagai string atau sebagai array byte:

String carAsString = objectMapper.writeValueAsString(car); 

3.2. JSON ke Objek Java

Di bawah ini adalah contoh sederhana untuk mengonversi String JSON menjadi 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 file yang berisi string 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

Alternatifnya, JSON dapat diurai menjadi objek JsonNode dan digunakan untuk mengambil data dari node tertentu:

String json = "{ \"color\" : \"Black\", \"type\" : \"FIAT\" }"; JsonNode jsonNode = objectMapper.readTree(json); String color = jsonNode.get("color").asText(); // Output: color -> Black 

3.4. Membuat Daftar Java Dari String Array JSON

Kita dapat mengurai JSON dalam bentuk array menjadi daftar 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 String JSON

Demikian pula, kita dapat mengurai JSON menjadi Peta Java :

String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }"; Map map = objectMapper.readValue(json, new TypeReference(){}); 

4. Fitur Lanjutan

Salah satu kekuatan terbesar dari perpustakaan Jackson adalah proses serialisasi dan deserialisasi yang sangat dapat disesuaikan.

Di bagian ini, kita akan membahas beberapa fitur lanjutan di mana respons JSON input atau output bisa berbeda dari objek yang menghasilkan atau mengonsumsi respons.

4.1. Mengonfigurasi Fitur Serialisasi atau Deserialisasi

Saat mengonversi objek JSON ke kelas Java, jika string JSON memiliki beberapa bidang baru, proses default akan menghasilkan pengecualian:

String jsonString = "{ \"color\" : \"Black\", \"type\" : \"Fiat\", \"year\" : \"1970\" }"; 

String JSON dalam contoh di atas dalam proses parsing default ke objek Java untuk Class Car akan menghasilkan pengecualian UnrecognizedPropertyException .

Melalui metode konfigurasi , kita dapat memperpanjang proses default 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(); 

Namun opsi lain didasarkan pada FAIL_ON_NULL_FOR_PRIMITIVES , yang menentukan apakah nilai null untuk nilai primitif diperbolehkan:

objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false); 

Demikian pula, FAIL_ON_NUMBERS_FOR_ENUM mengontrol jika nilai enum diizinkan untuk diserialkan / dideserialisasi sebagai angka:

objectMapper.configure(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS, false);

Anda dapat menemukan daftar lengkap fitur serialisasi dan deserialisasi di situs resmi.

4.2. Membuat Serializer atau Deserializer Kustom

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

Fitur kecil namun berguna lainnya yang tersedia melalui kelas DeserializationFeature adalah kemampuan untuk menghasilkan jenis koleksi yang kita inginkan dari respons Array JSON.

Misalnya, kita dapat menghasilkan hasilnya sebagai array:

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 Daftar :

String jsonCarArray = "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]"; ObjectMapper objectMapper = new ObjectMapper(); List listCar = objectMapper.readValue(jsonCarArray, new TypeReference
    
     (){}); // print cars
    

Informasi lebih lanjut tentang menangani koleksi dengan Jackson tersedia di sini.

5. Kesimpulan

Jackson adalah pustaka serialisasi / deserialisasi JSON yang solid dan matang untuk Java. The ObjectMapper API menyediakan cara mudah untuk mengurai dan menghasilkan JSON respon objek dengan banyak fleksibilitas. Artikel ini membahas fitur-fitur utama yang membuat perpustakaan ini begitu populer.

Kode sumber yang menyertai artikel dapat ditemukan di GitHub.