Flere Jackson-kommentarer

1. Oversigt

Denne artikel dækker nogle yderligere kommentarer, der ikke blev dækket af den foregående artikel, En guide til Jackson-kommentarer - vi gennemgår syv af disse.

2. @JsonIdentityReference

@JsonIdentityReference bruges til tilpasning af referencer til objekter, der vil blive serieliseret som objektidentiteter i stedet for fulde POJO'er. Det fungerer i samarbejde med @JsonIdentityInfo for at tvinge brugen af ​​objektidentiteter i hver serialisering, forskellig fra alt-men-første gang, når @JsonIdentityReference er fraværende. Dette par kommentarer er mest nyttigt, når man beskæftiger sig med cirkulære afhængigheder blandt objekter. Se afsnit 4 i artiklen Jackson - Bidirektionelt forhold for mere information.

For at demonstrere brugen @JsonIdentityReference, vil vi definere to forskellige bønneklasser uden og med denne kommentar.

Bønnen uden @JsonIdentityReference:

@JsonIdentityInfo (generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") offentlig klasse BeanWithoutIdentityReference {privat int id; privat strengnavn; // konstruktør, getters og setters}

Til bønnen ved hjælp af @JsonIdentityReference, vi vælger id ejendom skal være objektets identitet:

@JsonIdentityInfo (generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") @JsonIdentityReference (alwaysAsId = true) offentlig klasse BeanWithIdentityReference {privat int id; privat strengnavn; // konstruktør, getters og setters}

I det første tilfælde, hvor @JsonIdentityReference er fraværende, bliver bønnen serielt med alle detaljer om dens egenskaber:

BeanWithoutIdentityReference bean = new BeanWithoutIdentityReference (1, "Bean Without Identity Reference Annotation"); String jsonString = mapper.writeValueAsString (bønne);

Outputtet fra ovenstående serialisering:

{"id": 1, "name": "Bean Without Identity Reference Annotation"}

Hvornår @JsonIdentityReference bruges, ser bønnen i stedet som en simpel identitet:

BeanWithIdentityReference bean = new BeanWithIdentityReference (1, "Bean With Identity Reference Annotation"); String jsonString = mapper.writeValueAsString (bønne); assertEquals ("1", jsonString);

3. @JsonAppend

Det @JsonAppend annotation bruges til at tilføje virtuelle egenskaber til et objekt ud over almindelige, når objektet serialiseres. Dette er nødvendigt, når vi vil tilføje supplerende oplysninger direkte til en JSON-streng i stedet for at ændre klassedefinitionen. For eksempel kan det være mere praktisk at indsætte version metadata for en bønne til det tilsvarende JSON-dokument end at give den en yderligere egenskab.

Antag, at vi har en bønne uden @JsonAppend som følger:

offentlig klasse BeanWithoutAppend {private int id; privat strengnavn; // konstruktør, getters og setters}

En test vil bekræfte, at i fravær af @JsonAppend annotation, serialiseringsoutputtet indeholder ikke information om det supplerende version ejendom, på trods af at vi forsøger at tilføje til ObjectWriter objekt:

BeanWithoutAppend bean = new BeanWithoutAppend (2, "Bean Without Append Annotation"); ObjectWriter-forfatter = mapper.writerFor (BeanWithoutAppend.class) .withAttribute ("version", "1.0"); String jsonString = writer.writeValueAsString (bønne);

Serialiseringsoutputtet:

{"id": 2, "name": "Bean Without Append Annotation"}

Lad os sige, at vi har en bøn, der er kommenteret med @JsonAppend:

@JsonAppend (attrs = {@ JsonAppend.Attr (value = "version")}) offentlig klasse BeanWithAppend {privat int id; privat strengnavn; // konstruktør, getters og setters}

En lignende test som den forrige vil kontrollere, at når @JsonAppend annotering anvendes, den supplerende egenskab er inkluderet efter serialisering:

BeanWithAppend bean = ny BeanWithAppend (2, "Bean With Append Annotation"); ObjectWriter-forfatter = mapper.writerFor (BeanWithAppend.class) .withAttribute ("version", "1.0"); String jsonString = writer.writeValueAsString (bønne);

Resultatet af denne serialisering viser, at version ejendom er tilføjet:

{"id": 2, "name": "Bean With Append Annotation", "version": "1.0"}

4. @JsonNaming

Det @JsonNaming annotering bruges til at vælge navngivningsstrategier for egenskaber i serialisering, hvilket tilsidesætter standard. Bruger værdi element, kan vi specificere enhver strategi, herunder tilpassede strategier.

Ud over standard, som er LOWER_CAMEL_CASE (f.eks. lavereCamelCase), Jackson-biblioteket giver os fire andre indbyggede navngivningsstrategier for ejendom for nemheds skyld:

  • KEBAB_CASE: Navneelementer er adskilt af bindestreger, f.eks. kebab-kasse.
  • SMÅ BOGSTAVER: Alle bogstaver er små bogstaver uden separatorer, f.eks. små bogstaver.
  • SNAKE_CASE: Alle bogstaver er små bogstaver med understregninger som separatorer mellem navnelementer, f.eks. slangekuffert.
  • UPPER_CAMEL_CASE: Alle navnelementer, inklusive den første, starter med et stort bogstav, efterfulgt af små bogstaver, og der er ingen separatorer, f.eks. UpperCamelCase.

Dette eksempel illustrerer måden at serieisere egenskaber ved hjælp af slangesagnavne, hvor en ejendom hedder beanName er serieliseret som bønnenavn.

Givet en bønnedefinition:

@JsonNaming (PropertyNamingStrategy.SnakeCaseStrategy.class) offentlig klasse NamingBean {privat int id; private String beanName; // konstruktør, getters og setters}

Testen nedenfor viser, at den angivne navngivningsregel fungerer efter behov:

NamingBean bean = ny NamingBean (3, "Naming Bean"); String jsonString = mapper.writeValueAsString (bønne); assertThat (jsonString, containString ("bean_name"));

Det jsonString variabel indeholder følgende data:

{"id": 3, "bean_name": "Navngivning af bønne"}

5. @JsonPropertyDescription

Jackson-biblioteket er i stand til at oprette JSON-skemaer til Java-typer ved hjælp af et separat modul kaldet JSON Schema. Skemaet er nyttigt, når vi vil specificere forventet output, når vi serialiserer Java-objekter, eller for at validere et JSON-dokument inden deserialisering.

Det @JsonPropertyDescription kommentar tillader, at en menneskelig læsbar beskrivelse kan føjes til det oprettede JSON-skema ved at give beskrivelse Mark.

Dette afsnit anvender nedenstående bønne for at demonstrere kapaciteten hos @JsonPropertyDescription:

offentlig klasse PropertyDescriptionBean {privat int id; @JsonPropertyDescription ("Dette er en beskrivelse af navnet egenskab") privat strengnavn; // getters og setters}

Metoden til at generere et JSON-skema med tilføjelsen af beskrivelse feltet vises nedenfor:

SchemaFactoryWrapper wrapper = ny SchemaFactoryWrapper (); mapper.acceptJsonFormatVisitor (PropertyDescriptionBean.class, wrapper); JsonSchema jsonSchema = wrapper.finalSchema (); String jsonString = mapper.writeValueAsString (jsonSchema); assertThat (jsonString, containString ("Dette er en beskrivelse af navnet egenskab"));

Som vi kan se, var generationen af ​​JSON-skema vellykket:

{"type": "object", "id": "urn: jsonschema: com: baeldung: jackson: annotation: extra: PropertyDescriptionBean", "egenskaber": {"name": {"type": "string", " beskrivelse ":" Dette er en beskrivelse af navnegenskaben "}," id ": {" type ":" heltal "}}}

6. @JsonPOJOBuilder

Det @JsonPOJOBuilder annotation bruges til at konfigurere en builder-klasse til at tilpasse deserialisering af et JSON-dokument til at gendanne POJO'er, når navngivningskonventionen er forskellig fra standard.

Antag, at vi skal deserialisere følgende JSON-streng:

{"id": 5, "name": "POJO Builder Bean"}

Denne JSON-kilde vil blive brugt til at oprette en forekomst af POJOBuilderBean:

@JsonDeserialize (builder = BeanBuilder.class) offentlig klasse POJOBuilderBean {privat int identitet; private String beanName; // konstruktør, getters og setters}

Navnene på bønnens egenskaber er forskellige fra felterne i JSON-streng. Det er her @JsonPOJOBuilder kommer til undsætning.

Det @JsonPOJOBuilder annotering ledsages af to egenskaber:

  • buildMethodName: Navnet på no-arg-metoden, der bruges til at instantiere den forventede bønne efter binding af JSON-felter til bønnens egenskaber. Standardnavnet er bygge.
  • med præfiks: Navnepræfikset til automatisk detektion af matchning mellem JSON og bønnens egenskaber. Standardpræfikset er med.

Dette eksempel gør brug af BeanBuilder klasse nedenfor, som bruges på POJOBuilderBean:

@JsonPOJOBuilder (buildMethodName = "createBean", withPrefix = "construct") offentlig klasse BeanBuilder {private int idValue; private String nameValue; public BeanBuilder constructId (int id) {idValue = id; returner dette; } public BeanBuilder constructName (String name) {nameValue = name; returner dette; } offentlig POJOBuilderBean createBean () {returner ny POJOBuilderBean (idValue, nameValue); }}

I koden ovenfor har vi konfigureret @JsonPOJOBuilder at bruge en byggemetode kaldet createBean og konstruere præfiks for matchende egenskaber.

Anvendelsen af @JsonPOJOBuilder til en bønne er beskrevet og testet som følger:

String jsonString = "{\" id \ ": 5, \" name \ ": \" POJO Builder Bean \ "}"; POJOBuilderBean bean = mapper.readValue (jsonString, POJOBuilderBean.class); assertEquals (5, bean.getIdentity ()); assertEquals ("POJO Builder Bean", bean.getBeanName ());

Resultatet viser, at et nyt dataobjekt er blevet gendannet med succes fra en JSON-kilde på trods af en uoverensstemmelse i egenskabernes navne.

7. @JsonTypeId

Det @JsonTypeId annotation bruges til at indikere, at den annoterede egenskab skal serienummereres som type-id, når den inkluderer polymorf type information, snarere end som en almindelig egenskab. At polymorfe metadata bruges under deserialisering til at genskabe objekter af de samme undertyper, som de var før serialisering, snarere end af de erklærede supertyper.

For mere information om Jacksons håndtering af arv, se afsnit 2 i Arv i Jackson.

Lad os sige, at vi har en bønneklassedefinition som følger:

offentlig klasse TypeIdBean {privat int id; @JsonTypeId privat strengnavn; // konstruktør, getters og setters}

Den følgende test validerer det @JsonTypeId fungerer som det er meningen at:

mapper.enableDefaultTyping (DefaultTyping.NON_FINAL); TypeIdBean bean = ny TypeIdBean (6, "Type Id Bean"); String jsonString = mapper.writeValueAsString (bønne); assertThat (jsonString, containString ("Type Id Bean"));

Serialiseringsprocessens output:

["Type Id Bean", {"id": 6}]

8. @JsonTypeIdResolver

Det @JsonTypeIdResolver annotation bruges til at betegne en brugerdefineret type identitetshåndterer i serialisering og deserialisering. Denne handler er ansvarlig for konvertering mellem Java-typer og type-id inkluderet i et JSON-dokument.

Antag, at vi vil integrere typeoplysninger i en JSON-streng, når vi beskæftiger os med følgende klassehierarki.

Det AbstraktBønne superklasse:

@JsonTypeInfo (use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "@type") @JsonTypeIdResolver (BeanIdResolver.class) public class AbstractBean {private int id; beskyttet AbstractBean (int id) {this.id = id; } // no-arg konstruktør, getter og setter}

Det FirstBean underklasse:

offentlig klasse FirstBean udvider AbstractBean {String firstName; offentlig FirstBean (int id, String name) {super (id); setFirstName (navn); } // no-arg konstruktør, getter og setter}

Det LastBean underklasse:

offentlig klasse LastBean udvider AbstractBean {streng efternavn; offentlig LastBean (int id, String name) {super (id); setLastName (navn); } // no-arg konstruktør, getter og setter}

Forekomster af disse klasser bruges til at udfylde en BeanContainer objekt:

offentlig klasse BeanContainer {private List bønner; // getter og setter}

Vi kan se, at AbstraktBønne klasse er kommenteret med @JsonTypeIdResolver, hvilket indikerer, at det bruger en brugerdefineret TypeIdResolver at beslutte, hvordan subtypeoplysninger skal inkluderes i serialisering, og hvordan man bruger metadataene omvendt.

Her er resolverklassen til håndtering af inkludering af typeoplysninger:

offentlig klasse BeanIdResolver udvider TypeIdResolverBase {privat JavaType superType; @Override public void init (JavaType baseType) {superType = baseType; } @ Override public Id getMechanism () {return Id.NAME; } @ Override public String idFromValue (Object obj) {return idFromValueAndType (obj, obj.getClass ()); } @Override public String idFromValueAndType (Object obj, Class subType) {String typeId = null; switch (subType.getSimpleName ()) {case "FirstBean": typeId = "bean1"; pause; sag "LastBean": typeId = "bean2"; } return typeId; } @ Overstyr offentlig JavaType typeFromId (DatabindContext context, String id) {Class subType = null; switch (id) {case "bean1": subType = FirstBean.class; pause; sag "bean2": subType = LastBean.class; } returner context.constructSpecializedType (superType, subType); }}

De to mest bemærkelsesværdige metoder er idFromValueAndType og typeFromId, hvor førstnævnte fortæller hvordan man skal inkludere typeoplysninger, når POJO'er serialiseres, og sidstnævnte bestemmer undertyperne af genoprettede objekter ved hjælp af disse metadata.

For at sikre, at både serialisering og deserialisering fungerer godt, lad os skrive en test for at validere den komplette status.

Først skal vi instantiere en bønnebeholder og bønneklasser og derefter udfylde beholderen med bønneinstanser:

FirstBean bean1 = ny FirstBean (1, "Bean 1"); LastBean bean2 = ny LastBean (2, "Bean 2"); Listebønner = ny ArrayList (); bønner.add (bønne1); bønner.add (bønne2); BeanContainer serializedContainer = ny BeanContainer (); serializedContainer.setBeans (bønner);

Dernæst BeanContainer objekt serieliseres, og vi bekræfter, at den resulterende streng indeholder typeoplysninger:

String jsonString = mapper.writeValueAsString (serializedContainer); assertThat (jsonString, containString ("bean1")); assertThat (jsonString, containString ("bean2"));

Resultatet af serialisering er vist nedenfor:

{"beans": [{"@type": "bean1", "id": 1, "firstName": "Bean 1"}, {"@type": "bean2", "id": 2, "lastName ":" Bean 2 "}]}

Denne JSON-struktur vil blive brugt til at genskabe genstande med de samme undertyper som før serialisering. Her er implementeringstrinene for deserialisering:

BeanContainer deserializedContainer = mapper.readValue (jsonString, BeanContainer.class); Liste beanList = deserializedContainer.getBeans (); assertThat (beanList.get (0), instanceOf (FirstBean.class)); assertThat (beanList.get (1), instanceOf (LastBean.class));

9. Konklusion

Denne tutorial har forklaret flere mindre almindelige Jackson-kommentarer i detaljer. Implementeringen af ​​disse eksempler og kodestykker kan findes i et GitHub-projekt.


$config[zx-auto] not found$config[zx-overlay] not found