"Selam dostum!"

"Merhaba Diego."

"Burada JSON serileştirmenin temellerini öğrendiğinizi görüyorum?"

"'Temel bilgiler' ne demek? Çok şey biliyorum!"

"Çok safsın. İşin yarısını bile bilmiyorsun. En fazla yüzde on."

"Şaka yapıyorsun. Başka ne var?"

"Bir nesne hiyerarşisinin serisini kaldırma (polimorfik seriyi kaldırma), koleksiyonların serisini kaldırma ve çok daha fazlası! Jackson çerçevesi büyük ve güçlü. Dürüst olmak gerekirse, sadece yüzeyi çizmeye başladınız."

"Tamam, o zaman bana anlat - seni dinliyorum."

"Her derste daha akıllı olmaktan gerçekten zevk alıyorum!"

"Pekala, yardım etmek benim için bir zevk, robot arkadaşım!"

"Hazır mısın? O halde dinle."

"Daha önce öğrendiğiniz gibi, ek açıklamalar hem serileştirme hem de seriden çıkarma için kullanılır. Pratikte, seri hale getirme, seriden çıkarmaya göre çok daha az bilgi gerektirir. Örneğin:"

Java sınıfı JSON
class Cat
{
 public String name = "missy";
 public Cat[] cats = new Cat[0];
}
{
 "name": "missy",
 "cats": []
}
class Cat
{
 public String name = "missy";
 public List cats = new ArrayList<Cat>();
}
{
 "name": "missy",
 "cats": []
}
class Cat
{
 public String name = "missy";
 public List cats = new LinkedList<Cat>();
}
{
 "name": "missy",
 "cats": []
}

"Array, ArrayList, LinkedList ve diğer sınıfların örnekleri JSON dizilerine dönüştürülür."

"Ama bir JSON dizisinin serisini kaldırdığınızda, hangi nesneyi oluşturmalısınız: ArrayList mi yoksa LinkedList mi?"

"Doğru. Bir sınıf üyesi bir arayüz ise (ör. public List<Cat> cats ), ona hangi nesne atfedilmelidir?"

"Alana ek açıklamalar ekleyebilir veya seriden çıkarma sırasında hedef sınıfları açıkça belirtebiliriz. Şu örneğe bakın:"

JSON'dan bir nesneyi dönüştürme
public static void main(String[] args) throws IOException
{
 String jsonString = ""{\"name\":\"Missy\",\"cats\":[{\"name\":\"Timmy\"},{\"name\":\"Killer\"}]}"";
 StringReader reader = new StringReader(jsonString);
 ObjectMapper mapper = new ObjectMapper();
 Cat cat = mapper.readValue(reader, TypeFactory.collectionType(ArrayList.class, Cat.class));
}
Nesneleri JSON'dan seri hale getirilmiş bir sınıf
@JsonAutoDetect
class Cat {
 public String name;
 public List<Cat> cats = new ArrayList<>();
 Cat() {
 }
}

"Başka bir deyişle, seri durumdan çıkarma sırasında kullanılacak sınıfların listesini geçirmek için mapper .readValue yönteminin ikinci parametresini kullanabiliriz . "

"Beğendim. Bu uygun. Böylece bir JSON dizisini seri durumundan çıkarıp, ihtiyacınız olan her şeye, bir ArrayList'e veya bir LinkedList'e dönüştürebilirsiniz.

"Açıklama kullanmaktan da bahsetmiştin. Bunu nasıl yapıyorsun?"

"Kolay. Örneğin:"

JSON'dan bir nesneyi dönüştürme
public static void main(String[] args) throws IOException
{
 String jsonString = ""{\"name\":\"Missy\",\"cats\":[{\"name\":\"Timmy\"},{\"name\":\"Killer\"}]}"";
 StringReader reader = new StringReader(jsonString);

 ObjectMapper mapper = new ObjectMapper();

 Cat cat = mapper.readValue(reader, Cat.class);
}
Nesneleri JSON'dan seri hale getirilmiş bir sınıf
@JsonAutoDetect
class Cat
{
 public String name;
 @JsonDeserialize(as = ArrayList.class, contentAs = Cat.class)
 public List<Cat> cats = new ArrayList<>();
 Cat() {
 }
}

" List arayüzünün hangi uygulamasının kullanılacağını belirtmek için @JsonDeserialize(as = ArrayList.class, contentAs = Cat.class) ek açıklamasını 5. satıra ekliyoruz ."

"Ah. Anlıyorum. Bu gerçekten çok basit."

"Ama dahası da var. Bir Listedeki veri türünün aynı zamanda bir arabirim olduğunu varsayalım! Ne yapardınız?"

"Burada da bir açıklama kullanıyor muyuz?"

"Evet, aynısı. Parametre türünü belirtmek için de kullanabilirsiniz. Bunun gibi:"

Koleksiyon türü veri türü nasıl ayarlanır
Liste @JsonDeserialize(contentAs = ValueTypeImpl.class)
Harita @JsonDeserialize(keyAs = KeyTypeImpl.class)

"Harika! Önceden tahmin edemediğimiz çeşitli durumlar için gereken çok sayıda ek açıklama var."

"Hepsi bu kadar değil. Bu da bizi asıl konuya getiriyor: gerçek projelerde, sınıflar genellikle neredeyse her yerde kullanılan aynı temel sınıfı veya arabirimi miras alır. Şimdi de bu tür sınıfları içeren bir veri yapısını seri durumundan kaldırmanız gerektiğini hayal edin. Örneğin:"

Bir nesneyi JSON'a dönüştürme
public static void main(String[] args) throws IOException
{
 Cat cat = new Cat();
 cat.name = "Missy";
 cat.age = 5;

 Dog dog = new Dog();
 dog.name = "Killer";
 dog.age = 8;
 dog.owner = "Bill Jefferson";

 ArrayList<Pet> pets = new ArrayList<Pet>();
 pets.add(cat);
 pets.add(dog);

 StringWriter writer = new StringWriter();
 ObjectMapper mapper = new ObjectMapper();
 mapper.writeValue(writer, pets);
 System.out.println(writer.toString());
}
Nesneleri JSON'a dönüşen bir sınıf
@JsonAutoDetect
class Pet
{
 public String name;
}

@JsonAutoDetect
class Cat extends Pet
{
 public int age;
}

@JsonAutoDetect
class Dog extends Pet
{
 public int age;
 public String owner;
}
Serileştirme sonucu ve ekran çıktısı:
[
 { "name" : "Missy", "age" : 5},
 { "name" : "Killer", "age" : 8 , "owner" : "Bill Jeferson"}
]

"Serileştirme sonucuna dikkat edin."

"Aslında diğer sınıfların verilerinden ayırt edilemez olduğundan, bu verileri bir Java nesnesine seri hale getiremiyoruz."

"Bazı ayırt edici özellikler var: Köpeğin sahiplik alanı var."

"Evet, ancak bu alan boş olabilir veya serileştirme sırasında tamamen atlanabilir."

"Peki, bildiğimiz ek açıklamaları kullanarak veri türünü belirleyemez miyiz?"

"Hayır. Serileştirmeden sonra, tek bir koleksiyonda çeşitli Kedi ve Köpek nesnelerinin yanı sıra Pet'ten miras alınabilecek bir düzine başka sınıf bulunmalıdır."

"Burada ne yapabilirsin?"

"Burada iki şey kullanılıyor."

"Öncelikle bir türü diğerinden ayırt etmek için belirli bir alan seçilir. Eğer böyle bir alan yoksa oluşturulur."

"İkincisi, «polimorfik seriyi kaldırma» sürecini kontrol etmenize izin veren özel ek açıklamalar var. Yapabilecekleriniz şunlardır:"

Bir nesneyi JSON'a dönüştürme
public static void main(String[] args) throws IOException
{
 Cat cat = new Cat();
 cat.name = "Missy";
 cat.age = 5;

 Dog dog = new Dog();
 dog.name = "Killer";
 dog.age = 8;
 dog.owner = "Bill Jeferson";

 House house = new House();
 house.pets.add(dog);
 house.pets.add(cat);

 StringWriter writer = new StringWriter();
 ObjectMapper mapper = new ObjectMapper();
 mapper.writeValue(writer, house);
 System.out.println(writer.toString());
}
Nesneleri JSON'a dönüşen bir sınıf
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = Cat.class, name = "cat"),
@JsonSubTypes.Type(value = Dog.class, name = "dog")
})
class Pet
{
 public String name;
}

class Cat extends Pet
{
 public int age;
}

class Dog extends Pet
{
 public int age;
 public String owner;
}

class House
{
 public List<Pet> pets = new ArrayList<>();
}
Serileştirme sonucu ve ekran çıktısı:
{
 "pets" : [
 {"type" : "dog", "name" : "Killer", "age" : 8, "owner" : "Bill Jeferson"},
 {"type" : "cat", "name" : "Missy", "age" : 5}
]
}

Ek açıklamaları kullanarak, JSON gösteriminin, Cat sınıfı için cat değerini ve Dog sınıfı için dog değerini tutacak type adlı özel bir alan içereceğini belirtiyoruz . Bu bilgi, bir nesneyi düzgün bir şekilde seri durumdan çıkarmak için yeterlidir: seri durumdan çıkarma sırasında, oluşturulacak nesnenin türü , tür alanının değeri tarafından belirlenir.

"Bazen sınıf adı, tür alanının değeri olarak kullanılır (örneğin, «com.example.entity.Cat.class»), ancak bu iyi bir uygulama değildir. JSON'umuzu alan harici bir uygulama adlarını nasıl bilebilir? Daha da kötüsü, sınıflar bazen yeniden adlandırılır. Belirli bir sınıfı tanımlamak için benzersiz bir ad kullanmak daha iyidir."

"Harika! Ah. Seri durumdan çıkarmanın bu kadar karmaşık olduğunu fark etmemiştim. Ve ince ayar yapabileceğiniz o kadar çok şey var ki."

"Evet. Bunlar senin için yeni kavramlar ama bu seni dahi bir programcı yapacak türden pratik bilgiler."

"Amigo harika bir programcı. Harika!"

"Tamam. Git ve biraz ara ver."