További Jackson kommentárok
1. Áttekintés
Ez a cikk néhány további megjegyzéssel foglalkozik, amelyekre nem vonatkozott az előző cikk, A Guide to Jackson Annotations - ezek közül héten megyünk keresztül.
2. @JsonIdentityReference
@JsonIdentityReference olyan objektumokra történő hivatkozások testreszabására szolgál, amelyek objektumazonosítókként lesznek sorosítva a teljes POJO-k helyett. A következőkkel együttműködve működik @JsonIdentityInfo kényszeríteni az objektumazonosságok használatát minden sorosításban, eltérően az első alkalom kivételével @JsonIdentityReference hiányzik. Ez a pár annotáció akkor hasznos, ha az objektumok körkörös függőségeivel foglalkozunk. További információkért olvassa el a Jackson - Kétirányú kapcsolat cikk 4. szakaszát.
A használat bemutatása érdekében @JsonIdentityReference, két különböző babosztályt fogunk meghatározni, anélkül és ezzel az annotációval.
A bab nélkül @JsonIdentityReference:
@JsonIdentityInfo (generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") public class BeanWithoutIdentityReference {private int id; privát karakterlánc neve; // kivitelező, mérőeszközök és beállítók}
A bab használatához @JsonIdentityReference, választjuk a id tulajdonság az objektumazonosság:
@JsonIdentityInfo (generátor = ObjectIdGenerators.PropertyGenerator.class, tulajdonság = "id") @JsonIdentityReference (alwaysAsId = true) nyilvános osztály BeanWithIdentityReference {private int id; privát karakterlánc neve; // kivitelező, mérőeszközök és beállítók}
Az első esetben hol @JsonIdentityReference hiányzik, a babot sorozatosan adják meg annak tulajdonságairól:
BeanWithoutIdentityReference bean = új BeanWithoutIdentityReference (1, "Bean Identity Reference Annotation nélkül"); Karakterlánc jsonString = mapper.writeValueAsString (bab);
A fenti sorosítás kimenete:
{"id": 1, "name": "Bean Identity Reference Annotation nélkül"}
Mikor @JsonIdentityReference használatos, a babot egyszerű identitásként sorosítják:
BeanWithIdentityReference bean = new BeanWithIdentityReference (1, "Bean With Identity Reference Annotation"); Karakterlánc jsonString = mapper.writeValueAsString (bab); assertEquals ("1", jsonString);
3. @JsonAppend
A @JsonAppend annotációval virtuális tulajdonságokat adhat hozzá egy objektumhoz a szokásosakon kívül, amikor az objektum sorosítva van. Erre akkor van szükség, ha az osztálydefiníció megváltoztatása helyett kiegészítő információkat akarunk közvetlenül hozzáadni egy JSON karakterlánchoz. Például kényelmesebb lehet a változat a metaadatok a megfelelő JSON dokumentumhoz, mint hogy további tulajdonságot nyújtson számára.
Tegyük fel, hogy van babunk anélkül @JsonAppend alábbiak szerint:
public class BeanWithoutAppend {private int id; privát karakterlánc neve; // kivitelező, mérőeszközök és beállítók}
Egy teszt megerősíti, hogy a @JsonAppend megjegyzés, a szerializációs kimenet nem tartalmaz információt a kiegészítőről változat ingatlan, annak ellenére, hogy megpróbáljuk hozzáadni a ObjectWriter tárgy:
BeanWithoutAppend bean = új BeanWithoutAppend (2, "Bab annotáció nélkül"); ObjectWriter író = mapper.writerFor (BeanWithoutAppend.class) .withAttribute ("verzió", "1.0"); Karakterlánc jsonString = író.writeValueAsString (bab);
A sorosítási kimenet:
{"id": 2, "name": "Bab annotation hozzáadása nélkül"}
Tegyük fel, hogy van egy babunk, amellyel jegyzetelt @JsonAppend:
@JsonAppend (attrs = {@ JsonAppend.Attr (value = "version")}) public class BeanWithAppend {private int id; privát karakterlánc neve; // kivitelező, mérőeszközök és beállítók}
Az előzőhöz hasonló teszt igazolja, hogy amikor a @JsonAppend annotáció kerül alkalmazásra, a sorozást követően a kiegészítő tulajdonság szerepel:
BeanWithAppend bean = new BeanWithAppend (2, "Bab kiegészítõ kommentárral"); ObjectWriter író = mapper.writerFor (BeanWithAppend.class) .withAttribute ("verzió", "1.0"); Karakterlánc jsonString = író.writeValueAsString (bab);
A sorosítás eredménye azt mutatja, hogy a változat tulajdonság hozzáadva:
{"id": 2, "name": "Bean with annotation", "version": "1.0"}
4. @JsonNaming
A @JsonNaming az annotációt használják a tulajdonságok elnevezési stratégiáinak kiválasztására a sorozatosítás során, felülírva az alapértelmezettet. Használni a érték elemet, megadhatunk bármilyen stratégiát, beleértve az egyediakat is.
Az alapértelmezett mellett, ami LOWER_CAMEL_CASE (például. lowerCamelCase), A Jackson könyvtár további négy beépített ingatlan-elnevezési stratégiát kínál nekünk a kényelem érdekében:
- KEBAB_CASE: A névelemeket kötőjelek választják el, pl. kebab-tok.
- LOWER_CASE: Minden betű kisbetű, elválasztó nélkül, pl. kisbetűs.
- SNAKE_CASE: Minden betű kisbetűs, aláhúzással, mint elválasztókkal a névelemek között, pl. kígyóház.
- UPPER_CAMEL_CASE: Minden névelem, beleértve az elsőt is, nagybetűvel kezdődik, majd kisbetűket követ, és nincsenek elválasztók, pl. UpperCamelCase.
Ez a példa bemutatja a tulajdonságok sorosítási módját kígyónevek használatával, ahol egy tulajdonság megnevezve babnév sorozatszámú babnév.
Adott egy babdefiníciót:
@JsonNaming (PropertyNamingStrategy.SnakeCaseStrategy.class) public class NamingBean {private int id; private String beanName; // kivitelező, mérőeszközök és beállítók}
Az alábbi teszt azt mutatja, hogy a megadott elnevezési szabály a kívánt módon működik:
NamingBean bab = új NamingBean (3, "Bab elnevezése"); Karakterlánc jsonString = mapper.writeValueAsString (bab); assertThat (jsonString, tartalmazzaString ("babnév"));
A jsonString változó a következő adatokat tartalmazza:
{"id": 3, "bean_name": "Bean elnevezése"}
5. @JsonPropertyDescription
A Jackson könyvtár JSON-sémákat hozhat létre Java-típusokhoz a JSON-séma nevű külön modul segítségével. A séma akkor hasznos, ha meg akarjuk adni a várható kimenetet a Java-objektumok sorosítása során, vagy egy JSON-dokumentumot érvényesítenünk kell a deserializálás előtt.
A @JsonPropertyDescription az annotáció lehetővé teszi egy ember számára olvasható leírás hozzáadását a létrehozott JSON-sémához a leírás terület.
Ez a szakasz az alábbiakban ismertetett babot használja fel a @JsonPropertyDescription:
public class PropertyDescriptionBean {private int id; @JsonPropertyDescription ("Ez a név tulajdonság leírása") privát karakterlánc neve; // szerelők és beállítók}
A JSON séma előállításának módszere a leírás mező az alábbiakban látható:
SchemaFactoryWrapper wrapper = új SchemaFactoryWrapper (); mapper.acceptJsonFormatVisitor (PropertyDescriptionBean.class, burkoló); JsonSchema jsonSchema = burkoló.finalSchema (); Karakterlánc jsonString = mapper.writeValueAsString (jsonSchema); assertThat (jsonString, tartalmazString ("Ez a név tulajdonság leírása"));
Mint láthatjuk, a JSON-séma generálása sikeres volt:
{"type": "object", "id": "urn: jsonschema: com: baeldung: jackson: annotation: extra: PropertyDescriptionBean", "properties": {"name": {"type": "string", " description ":" Ez a név tulajdonság leírása "}," id ": {" type ":" integer "}}}
6. @JsonPOJOBuilder
A @JsonPOJOBuilder annotációval konfigurálható egy készítő osztály egy JSON-dokumentum deserializációjának testreszabására POJO-k helyreállítására, ha a névadási szokás eltér az alapértelmezettől.
Tegyük fel, hogy deszerializálnunk kell a következő JSON karakterláncot:
{"id": 5, "name": "POJO Builder Bean"}
Ezt a JSON forrást fogják használni a POJOBuilderBean:
@JsonDeserialize (builder = BeanBuilder.class) public class POJOBuilderBean {private int identitás; private String beanName; // kivitelező, mérőeszközök és beállítók}
A bab tulajdonságainak megnevezése eltér a JSON karakterlánc mezőinek nevétől. Ez az, ahol @JsonPOJOBuilder megmentésre kerül.
A @JsonPOJOBuilder az annotációt két tulajdonság kíséri:
- buildMethodName: A no-arg módszer neve, amely a várható bab példányosítására szolgál, miután a JSON mezőket az adott bab tulajdonságaihoz kötötte. Az alapértelmezett név épít.
- withPrefix: A név előtag a JSON és a bab tulajdonságai közötti automatikus azonosításhoz. Az alapértelmezett előtag a val vel.
Ez a példa a BeanBuilder osztály alatt, amelyet a POJOBuilderBean:
@JsonPOJOBuilder (buildMethodName = "createBean", withPrefix = "construct") nyilvános osztály BeanBuilder {private int idValue; privát String nameValue; public BeanBuilder constructId (int id) {idValue = id; adja vissza ezt; } public BeanBuilder constructName (karakterlánc neve) {nameValue = név; adja vissza ezt; } public POJOBuilderBean createBean () {return new POJOBuilderBean (idValue, nameValue); }}
A fenti kódban konfiguráltuk a @JsonPOJOBuilder nevű építési módszert használni createBean és a konstrukció előtag a megfelelő tulajdonságokhoz.
A @JsonPOJOBuilder A babot a következőképpen írják le és tesztelik:
Karakterlánc jsonString = "{\" id \ ": 5, \" name \ ": \" POJO Builder Bean \ "}"; POJOBuilderBean bab = mapper.readValue (jsonString, POJOBuilderBean.class); assertEquals (5, bab.getIdentity ()); assertEquals ("POJO Builder Bean", bean.getBeanName ());
Az eredmény azt mutatja, hogy egy új adatobjektumot sikeresen újrateremtettek egy JSON-forrásból a tulajdonságok nevének eltérése ellenére.
7. @JsonTypeId
A @JsonTypeId az annotációt arra használják, hogy jelezzék, hogy az annotált tulajdonságot nem a szokásos tulajdonságként, hanem a tipusazonosítóként kell sorosítani, ha a polimorf típusú információkat tartalmazza. Ezt a polimorf metaadatot a deszeriálizálás során ugyanazon altípusú objektumok újrateremtésére használják, mint amilyenek a szerializáció előtt voltak, nem pedig a deklarált szupertípusokat.
Jackson örökségének kezelésével kapcsolatos további információkért lásd: Jackson öröklése 2. szakasza.
Tegyük fel, hogy a bab osztály definíciója a következő:
public class TypeIdBean {private int id; @JsonTypeId privát karakterlánc neve; // kivitelező, mérőeszközök és beállítók}
A következő teszt ezt érvényesíti @JsonTypeId úgy működik, ahogy célja:
mapper.enableDefaultTyping (DefaultTyping.NON_FINAL); TypeIdBean bab = új TypeIdBean (6, "Type Id Bean"); Karakterlánc jsonString = mapper.writeValueAsString (bab); assertThat (jsonString, tartalmazString ("Type Id Bean"));
A sorosítási folyamat kimenete:
["Type Id Bean", {"id": 6}]
8. @JsonTypeIdResolver
A @JsonTypeIdResolver az annotációt egy egyedi típusú identitáskezelő jelölésére használják a szerializációban és a deserializációban. Ez a kezelő felelős a JSON-dokumentumban szereplő Java-típusok és típus-azonosító közötti átalakításért.
Tegyük fel, hogy a következő információkat szeretnénk beágyazni egy JSON karakterláncba, amikor a következő osztályhierarchiával foglalkozunk.
A AbstractBean szuperosztály:
@JsonTypeInfo (use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "@type") @JsonTypeIdResolver (BeanIdResolver.class) public class AbstractBean {private int id; védett AbstractBean (int id) {this.id = id; } // no-arg konstruktor, getter és setter}
A FirstBean alosztály:
a FirstBean nyilvános osztály kiterjeszti az AbstractBean {String keresztnév; public FirstBean (int id, String name) {szuper (id); setFirstName (név); } // no-arg konstruktor, getter és setter}
A LastBean alosztály:
a LastBean nyilvános osztály kiterjeszti az AbstractBean {String vezetéknév; public LastBean (int id, String name) {szuper (id); setLastName (név); } // no-arg konstruktor, getter és setter}
Ezen osztályok példányait használják a BeanContainer tárgy:
public class BeanContainer {private List bab; // getter és setter}
Láthatjuk, hogy a AbstractBean osztályban van jelölve @JsonTypeIdResolver, jelezve, hogy szokást használ TypeIdResolver annak eldöntése, hogy miként vonják be az altípus adatait a sorosításba, és hogyan használják fel ezeket a metaadatokat fordítva.
Itt van a megoldó osztály a típusinformációk felvételére:
a BeanIdResolver public class kiterjeszti a TypeIdResolverBase {private JavaType superType; @Orride public void init (JavaType baseType) {superType = baseType; } @Orride public Id getMechanism () {return Id.NAME; } @Orride public String idFromValue (Object obj) {return idFromValueAndType (obj, obj.getClass ()); } @Orride public String idFromValueAndType (Object obj, Class subType) {String typeId = null; kapcsoló (subType.getSimpleName ()) {case "FirstBean": typeId = "bab1"; szünet; "LastBean" eset: typeId = "bab2"; } return typeId; } @Orride public JavaType typeFromId (DatabindContext context, String id) {Class subType = null; kapcsoló (id) {case "bab1": subType = FirstBean.class; szünet; case "bab2": subType = LastBean.class; } return context.constructSpecializedType (superType, subType); }}
A két legnevezetesebb módszer a idFromValueAndType és typeFromId, az előbbi megmondja a típusinformációk beépítésének módját a POJO-k sorosítása során, míg az utóbbiak meghatározzák az újra létrehozott objektumok altípusait e metaadatok felhasználásával.
Annak érdekében, hogy a szerializáció és a deserializáció egyaránt jól működjön, írjunk egy tesztet a teljes előrehaladás érvényesítésére.
Először be kell állítanunk egy babtartályt és babosztályokat, majd töltsük fel ezt a tartályt babpéldányokkal:
FirstBean bab1 = új FirstBean (1, "Bab 1"); LastBean bab2 = new LastBean (2, "Bab 2"); Listabab = new ArrayList (); bab.add (bab1); bab.add (bab2); BeanContainer serializedContainer = új BeanContainer (); serializedContainer.setBeans (bab);
Ezután a BeanContainer Az objektum sorosítva van, és megerősítjük, hogy a kapott karakterlánc típusinformációt tartalmaz:
Karakterlánc jsonString = mapper.writeValueAsString (serializedContainer); assertThat (jsonString, tartalmazzaString ("bab1")); assertThat (jsonString, tartalmazzaString ("bab2"));
A sorosítás kimenete az alábbiakban látható:
{"bab": [{"@type": "bab1", "id": 1, "keresztnév": "Bab 1"}, {"@type": "bab2", "id": 2, "vezetéknév ":" Bab 2 "}]}
Ezt a JSON struktúrát arra használják, hogy ugyanazon altípusú objektumokat hozza létre újra, mint a sorozatosítás előtt. A deserializáció megvalósításának lépései:
BeanContainer deserializedContainer = mapper.readValue (jsonString, BeanContainer.class); BeanList = deserializedContainer.getBeans () lista; assertThat (beanList.get (0), instanceOf (FirstBean.class)); assertThat (beanList.get (1), instanceOf (LastBean.class));
9. Következtetés
Ez a bemutató számos kevésbé elterjedt Jackson-feljegyzést ismertetett részletesen. Ezeknek a példáknak és kódrészleteknek a megvalósítása megtalálható egy GitHub projektben.