"Szia haver!"

– Szia, Diego.

"Látom, itt megtanulta a JSON szerializálás alapjait?"

"Mit értesz azon, hogy "alapok"? Sokat tudok!

– Annyira naiv. A felét nem tudod. Legfeljebb tíz százalék.

– Viccelsz. Mi van még?

"Objektumhierarchia deszerializálása (polimorf deserializáció), gyűjtemények deszerializálása és még sok minden más! A Jackson-keret nagy és erőteljes. Őszintén szólva, még csak most kezdte meg karcolni a felszínt."

"Rendben, akkor mesélj róla, én csak füles vagyok."

"Nagyon élvezem, hogy minden leckével okosabb leszek!"

– Nos, örömömre szolgál, hogy segíthetek, robotbarátom!

"Készen állsz? Akkor figyelj."

"Amint azt már megtanulta, a megjegyzéseket mind a szerializáláshoz, mind a szerializáláshoz használják. A gyakorlatban a szerializálás sokkal kevesebb információt igényel, mint a szerializálás. Például:"

Java osztály 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": []
}

"Az Array, ArrayList, LinkedList és más osztályok példányai JSON-tömbökké alakulnak."

"De amikor deszerializál egy JSON-tömböt, milyen objektumot kell létrehoznia: ArrayList vagy LinkedList?"

"Helyes. Ha egy osztálytag egy interfész (pl. nyilvános List<Cat> cats ), milyen objektumot kell hozzá rendelni?"

"Hozzáadhatunk további megjegyzéseket a mezőhöz, vagy kifejezetten jelezhetjük a célosztályokat a deszerializálás során. Nézze meg ezt a példát:"

Konvertálja az objektumot JSON-ból
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));
}
Osztály, amelynek objektumai a JSON-ból deszerializáltak
@JsonAutoDetect
class Cat {
 public String name;
 public List&ltCat> cats = new ArrayList<>();
 Cat() {
 }
}

"Más szóval, a leképező . readValue metódus második paraméterével átadhatjuk a deszerializálás során használandó osztályok listáját."

"Szeretem. Ez kényelmes. Így egy JSON-tömböt deszerializálhat, amire szüksége van, legyen az ArrayList vagy egy LinkedList.

– Említetted a kommentárok használatát is. Hogyan csinálod?

"Könnyű. Például:"

Konvertálja az objektumot JSON-ból
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);
}
Osztály, amelynek objektumai a JSON-ból deszerializáltak
@JsonAutoDetect
class Cat
{
 public String name;
 @JsonDeserialize(as = ArrayList.class, contentAs = Cat.class)
 public List&ltCat> cats = new ArrayList<>();
 Cat() {
 }
}

"Egyszerűen hozzáadjuk a @JsonDeserialize(as = ArrayList.class, contentAs = Cat.class) megjegyzést az 5. sorhoz, jelezve, hogy a Lista felület melyik implementációját kell használni."

"Ah. értem. Ez tényleg nagyon egyszerű."

"De van még több. Tegyük fel, hogy a Listában szereplő adattípus egyben interfész is! Mit tennél?"

– Itt is használunk annotációt?

"Igen, ugyanaz. A paraméter típusának jelzésére is használható. Így:"

Gyűjtemény típusa Hogyan állítsuk be az adattípust
Lista @JsonDeserialize(contentAs = ValueTypeImpl.class)
Térkép @JsonDeserialize(keyAs = KeyTypeImpl.class)

"Csodálatos! Nagyon sok megjegyzésre van szükség különféle helyzetekben, amelyeket nem tudunk előre látni."

"Ez még nem minden. És ezzel el is érkeztünk a fő fogáshoz: a valós projektekben az osztályok gyakran ugyanazt az alaposztályt vagy felületet öröklik, amelyet gyakorlatilag mindenhol használnak. És most képzeljük el, hogy egy ilyen osztályokat tartalmazó adatstruktúrát deszerializálni kell. Például:"

Konvertálja az objektumot JSON-ba
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());
}
Egy osztály, amelynek objektumai JSON-ba konvertálódnak
@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;
}
Sorozatosítás eredménye és képernyőkimenet:
[
 { "name" : "Missy", "age" : 5},
 { "name" : "Killer", "age" : 8 , "owner" : "Bill Jeferson"}
]

"Figyeljen a sorozatosítás eredményére."

"Nem tudjuk ezeket az adatokat Java objektummá deszerializálni, mivel lényegében megkülönböztethetetlenek a többi osztály adataitól."

"Van néhány megkülönböztető jellemző: a kutyának van gazdája."

"Igen, de lehet, hogy ez a mező nulla, vagy teljesen kihagyható a szerializálás során."

"Nos, nem tudnánk megadni az adattípust olyan megjegyzésekkel, amelyeket ismerünk?"

"Nem. A deszerializálás után egyetlen gyűjteménynek különféle macska és kutya objektumokat kell tartalmaznia, valamint egy tucat másik osztályt, amelyek örökölhetnek Pettől."

– Mi a fenét tudsz itt csinálni?

– Itt két dolgot használnak.

"Először egy bizonyos mezőt választanak ki, hogy megkülönböztessék az egyik típust a másiktól. Ha nincs ilyen, akkor létrejön."

"Másodszor vannak speciális megjegyzések, amelyek lehetővé teszik a «polimorf deserializáció» folyamatának vezérlését. A következőket teheti:

Konvertálja az objektumot JSON-ba
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());
}
Egy osztály, amelynek objektumai JSON-ba konvertálódnak
@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&ltPet> pets = new ArrayList<>();
}
Sorozatosítás eredménye és képernyőkimenet:
{
 "pets" : [
 {"type" : "dog", "name" : "Killer", "age" : 8, "owner" : "Bill Jeferson"},
 {"type" : "cat", "name" : "Missy", "age" : 5}
]
}

Annotációk használatával jelezzük, hogy a JSON-reprezentáció tartalmazni fog egy típus nevű speciális mezőt, amely a Cat (Macska ) osztályhoz tartozó cat értéket , a Dog osztály esetében pedig a dog értéket fogja tartalmazni . Ez az információ elegendő egy objektum megfelelő deszerializálásához: a deserializálás során a létrehozandó objektum típusát a típus mező értéke határozza meg.

"Néha az osztálynevet használják a típusmező értékeként (pl. «com.example.entity.Cat.class»), de ez nem jó gyakorlat. Honnan ismerné a JSON-unkat fogadó külső alkalmazás a Ami még rosszabb, az osztályokat néha átnevezzük. Jobb, ha egyedi nevet használunk egy adott osztály azonosítására."

"Csodálatos! Sóhajt. Nem tudtam, hogy a deserializáció ennyire bonyolult. És hogy annyi mindent lehet finomítani."

"Igen. Ezek új fogalmak számodra, de ez az a fajta gyakorlati tudás, amitől zseniális programozó leszel."

"Amigo klassz programozó. Menő!"

"Rendben. Menj és tarts egy kis szünetet."