עוד ביאורים לג'קסון

1. סקירה כללית

מאמר זה מכסה כמה הערות נוספות שלא סוקרו במאמר הקודם, מדריך להערות ג'קסון - נעבור על שבעה כאלה.

2. @JsonIdentityReference

@JsonIdentityReference משמש להתאמה אישית של הפניות לאובייקטים שיועברו לסידורי זהויות אובייקט במקום POJO מלאים. זה עובד בשיתוף פעולה עם @JsonIdentityInfo לאלץ שימוש בזהויות אובייקט בכל סדרת סדר, שונה מהפעם הראשונה @JsonIdentityReference נעדר. זוג הערות זה מועיל ביותר כאשר מתמודדים עם תלות מעגלית בין אובייקטים. אנא עיין בסעיף 4 במאמר הקשר ג'קסון - דו כיווני למידע נוסף.

על מנת להדגים את השימוש @JsonIdentityReference, נגדיר שתי מחלקות שעועית שונות, בלי ועם ההערה הזו.

השעועית בלי @JsonIdentityReference:

@JsonIdentityInfo (generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") מחלקה ציבורית BeanWithoutIdentityReference {מזהה פרטי פרטי; שם מחרוזת פרטי; // קונסטרוקטור, גטרים וקובעים}

לשימוש שעועית @JsonIdentityReference, אנו בוחרים את תְעוּדַת זֶהוּת המאפיין יהיה זהות האובייקט:

@JsonIdentityInfo (generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") @JsonIdentityReference (alwaysAsId = true) מחלקה ציבורית BeanWithIdentityReference {מזהה פרטי פרטי; שם מחרוזת פרטי; // קונסטרוקטור, גטרים וקובעים}

במקרה הראשון, איפה @JsonIdentityReference נעדר, שעועית זו מסודרת עם פרטים מלאים על תכונותיה:

BeanWithoutIdentityReference שעועית = BeanWithoutIdentityReference חדש (1, "שעועית ללא הערת הפניה לזהות"); מחרוזת jsonString = mapper.writeValueAsString (שעועית);

פלט הסידור לעיל:

{"id": 1, "name": "ביאון ללא הערת הפניה לזהות"}

מתי @JsonIdentityReference משמש, השעועית מסודרת בזהות פשוטה במקום:

BeanWithIdentityReference שעועית = חדש BeanWithIdentityReference (1, "שעועית עם הערת הפניה לזהות"); מחרוזת jsonString = mapper.writeValueAsString (שעועית); assertEquals ("1", jsonString);

3. @JsonAppend

ה @JsonAppend ההערה משמשת להוספת מאפיינים וירטואליים לאובייקט בנוסף לאלה הרגילים כאשר האובייקט מסדרת סדרתי. זה הכרחי כאשר אנו רוצים להוסיף מידע משלים ישירות למחרוזת JSON, במקום לשנות את הגדרת הכיתה. למשל, זה יכול להיות יותר נוח להכניס את ה- גִרְסָה מטא נתונים של שעועית למסמך JSON המקביל מאשר לספק לו נכס נוסף.

נניח שיש לנו שעועית בלי @JsonAppend כדלהלן:

מחלקה ציבורית BeanWithoutAppend {private id id; שם מחרוזת פרטי; // קונסטרוקטור, גטרים וקובעים}

מבחן יאשר כי בהיעדר ה- @JsonAppend ביאור, פלט הסידור אינו מכיל מידע על התוספת גִרְסָה נכס, למרות שאנו מנסים להוסיף ל ObjectWriter לְהִתְנַגֵד:

BeanWithoutAppend bean = BeanWithoutAppend חדש (2, "שעועית בלי להוסיף הערה"); כותב ObjectWriter = mapper.writerFor (BeanWithoutAppend.class) .withAttribute ("גרסה", "1.0"); מחרוזת jsonString = writer.writeValueAsString (שעועית);

פלט הסידור:

{"id": 2, "name": "שעועית בלי להוסיף הערה"}

עכשיו, בואו נגיד שיש לנו שעועית עם הערה @JsonAppend:

@JsonAppend (attrs = {@ JsonAppend.Attr (value = "version")}) בכיתה ציבורית BeanWithAppend {מזהה פרטי פרטי; שם מחרוזת פרטי; // קונסטרוקטור, גטרים וקובעים}

בדיקה דומה לזו הקודמת תאמת שכאשר ה- @JsonAppend ההערה מוחלת, המאפיין המשלים נכלל לאחר הסידור:

BeanWithAppend שעועית = חדש BeanWithAppend (2, "שעועית עם הוספת הערה"); כותב ObjectWriter = mapper.writerFor (BeanWithAppend.class) .withAttribute ("גרסה", "1.0"); מחרוזת jsonString = writer.writeValueAsString (שעועית);

הפלט של אותה סדרה מראה כי ה- גִרְסָה נכס נוסף:

{"id": 2, "name": "שעועית עם הוספת הערה", "גרסה": "1.0"}

4. @JsonNaming

ה @JsonNaming הערה משמשת לבחירת אסטרטגיות שמות עבור מאפיינים בסידור, ובכך עוקפת את ברירת המחדל. משתמש ב ערך אנו יכולים לציין כל אסטרטגיה, כולל אסטרטגיות מותאמות אישית.

בנוסף לברירת המחדל, שהיא LOWER_CAMEL_CASE (לְמָשָׁל. קפל תחתון), ספריית ג'קסון מספקת לנו ארבע אסטרטגיות מובנות נוספות למתן שמות נכסים לנוחיותכם:

  • KEBAB_CASE: אלמנטים של שמות מופרדים על ידי מקפים, למשל. מארז קבב.
  • LOWER_CASE: כל האותיות קטנות ללא מפרידים, למשל. אותיות קטנות.
  • SNAKE_CASE: כל האותיות קטנות עם קו תחתון כמפריד בין רכיבי השם, למשל. נחש נחש.
  • UPPER_CAMEL_CASE: כל רכיבי השם, כולל הראשון, מתחילים באות באותיות רישיות, ואחריהם באותיות קטנות ואין מפרידים, למשל. UpperCamelCase.

דוגמה זו תמחיש את הדרך לסידור נכסים באמצעות שמות של ארז נחש, שם שם מאפיין שם שעועית מסודר בתור שם שעועית.

ניתן הגדרת שעועית:

@JsonNaming (PropertyNamingStrategy.SnakeCaseStrategy.class) מחלקה ציבורית NamingBean {מזהה פרטי פרטי; פרטי שעועית מחרוזת; // קונסטרוקטור, גטרים וקובעים}

הבדיקה שלהלן מדגימה כי כלל השמות שצוין פועל כנדרש:

NamingBean שעועית = חדש NamingBean (3, "שמות שעועית"); מחרוזת jsonString = mapper.writeValueAsString (שעועית); assertThat (jsonString, containString ("שם שעועית"));

ה jsonString משתנה מכיל את הנתונים הבאים:

{"id": 3, "bean_name": "Naming Bean"}

5. @JsonPropertyDescription

ספריית ג'קסון מסוגלת ליצור סכימות JSON לסוגי Java בעזרת מודול נפרד הנקרא JSON Schema. הסכימה שימושית כאשר אנו רוצים לציין פלט צפוי בעת סדרת אובייקטים של Java, או לאמת מסמך JSON לפני עריכה מחדש.

ה @JsonPropertyDescription ביאור מאפשר להוסיף תיאור קריא אנושי לסכמת JSON שנוצרה על ידי מתן ה- תיאור שדה.

סעיף זה עושה שימוש בשעועית המוצהרת להלן כדי להדגים את יכולותיה של @JsonPropertyDescription:

Class class PropertyDescriptionBean {מזהה פרטי פרטי; @JsonPropertyDescription ("זהו תיאור של מאפיין השם") שם פרטי מחרוזת; // גטרים וקובעים}

השיטה ליצירת סכימת JSON בתוספת ה- תיאור שדה מוצג להלן:

SchemaFactoryWrapper wrapper = SchemaFactoryWrapper חדש (); mapper.acceptJsonFormatVisitor (PropertyDescriptionBean.class, wrapper); JsonSchema jsonSchema = wrapper.finalSchema (); מחרוזת jsonString = mapper.writeValueAsString (jsonSchema); assertThat (jsonString, containString ("זהו תיאור של מאפיין השם"));

כפי שאנו רואים, הדור של סכמת JSON הצליח:

{"type": "object", "id": "urn: jsonschema: com: baeldung: jackson: annotation: extra: PropertyDescriptionBean", "properties": {"name": {"type": "string", " תיאור ":" זהו תיאור של מאפיין השם "}," id ": {" type ":" integer "}}}

6. @JsonPOJOBuilder

ה @JsonPOJOBuilder הערה משמשת לתצורה של מחלקה לבונה להתאמה אישית של עריכה מחדש של מסמך JSON לשחזור POJOs כאשר מוסכמת השמות שונה מברירת המחדל.

נניח שעלינו לבטל את ערכת המחרוזת הבאה של JSON:

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

מקור JSON זה ישמש ליצירת מופע של ה- POJOBuilderBean:

@JsonDeserialize (builder = BeanBuilder.class) POJOBuilderBean בכיתה ציבורית {זהות אינטנסיבית פרטית; פרטי שעועית מחרוזת; // קונסטרוקטור, גטרים וקובעים}

שמות מאפייני השעועית שונים מאלה של השדות במחרוזת JSON. זה איפה @JsonPOJOBuilder מגיע להצלה.

ה @JsonPOJOBuilder ההערה מלווה בשני מאפיינים:

  • buildMethodName: שמה של שיטת ה- no-arg המשמשת לאינסטינציה של השעועית הצפויה לאחר כריכת שדות JSON למאפייני אותה שעועית. שם ברירת המחדל הוא לִבנוֹת.
  • withPrefix: קידומת השם לזיהוי אוטומטי של התאמה בין מאפייני ה- JSON והשעועית. קידומת ברירת המחדל היא עם.

דוגמה זו עושה שימוש ב- BeanBuilder בכיתה למטה, המשמשת ב- POJOBuilderBean:

@JsonPOJOBuilder (buildMethodName = "createBean", withPrefix = "construct") מחלקה ציבורית BeanBuilder {private int idValue; פרטי מחרוזת nameValue; ציבורי BeanBuilder buildId (int id) {idValue = id; להחזיר את זה; } build BeanBuilder ציבורי (שם מחרוזת) {nameValue = name; להחזיר את זה; } POJOBuilderBean createBean () {להחזיר POJOBuilderBean חדש (idValue, nameValue); }}

בקוד לעיל הגדרנו את ה- @JsonPOJOBuilder להשתמש בשיטת בנייה הנקראת createBean וה לִבנוֹת קידומת להתאמת מאפיינים.

היישומון של @JsonPOJOBuilder לשעועית מתואר ונבדק באופן הבא:

מחרוזת jsonString = "{\" id \ ": 5, \" name \ ": \" POJO Builder Bean \ "}"; POJOBuilderBean שעועית = mapper.readValue (jsonString, POJOBuilderBean.class); assertEquals (5, bean.getIdentity ()); assertEquals ("POJO Builder Bean", bean.getBeanName ());

התוצאה מראה כי אובייקט נתונים חדש נוצר בהצלחה ממקור JSON למרות אי התאמה בשמות המאפיינים.

7. @JsonTypeId

ה @JsonTypeId הערה משמשת כדי לציין כי יש לסדר את המאפיין המאושר כמזהה סוג כאשר הוא כולל מידע מסוג פולימורפי ולא כמאפיין רגיל. מטא-נתונים פולימורפיים אלה משמשים במהלך עריקת הריסול כדי ליצור מחדש אובייקטים מאותם תת-סוגים שהיו לפני סדרת הסידור, ולא של סוגי העל המוצהרים.

למידע נוסף אודות הטיפול בג'קסון בירושה, ראה סעיף 2 לירושה בג'קסון.

נניח שיש לנו הגדרה של שעועית כדלקמן:

מחלקה ציבורית TypeIdBean {מזהה פרטי פרטי; @JsonTypeId שם מחרוזת פרטי; // קונסטרוקטור, גטרים וקובעים}

המבחן הבא מאמת זאת @JsonTypeId עובד כפי שהוא אמור:

mapper.enableDefaultTyping (DefaultTyping.NON_FINAL); TypeIdBean שעועית = חדש TypeIdBean (6, "סוג שעועית מזהה"); מחרוזת jsonString = mapper.writeValueAsString (שעועית); assertThat (jsonString, containString ("סוג שעועית מזהה"));

פלט תהליך הסידור:

["סוג שעועית מזהה", {"id": 6}]

8. @JsonTypeIdResolver

ה @JsonTypeIdResolver הערה משמשת לציון מטפל בזהות מסוג מותאם אישית בסידור ועריקול. מטפל זה אחראי להמרה בין סוגי Java ו- type id הכלולים במסמך JSON.

נניח שברצוננו להטמיע מידע מסוג במחרוזת JSON כאשר אנו עוסקים בהיררכיית המחלקה הבאה.

ה תקציר שעועית מעמד-על:

@JsonTypeInfo (use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "@type") @JsonTypeIdResolver (BeanIdResolver.class) class public AbstractBean {מזהה פרטי פרטי; מוגן AbstractBean (int id) {this.id = id; } // בנאי ללא ארג, גטר וקובע}

ה FirstBean תת מחלקה:

מחלקה ציבורית FirstBean מרחיבה את AbstractBean {String firstName; FirstBean ציבורי (מזהה int, שם מחרוזת) {super (id); setFirstName (שם); } // בנאי ללא ארג, גטר וקובע}

ה LastBean תת מחלקה:

המחלקה הציבורית LastBean מרחיבה את AbstractBean {שם המחרוזת; LastBean ציבורי (מזהה int, שם מחרוזת) {super (id); setLastName (שם); } // בנאי ללא ארג, גטר וקובע}

מופעים של שיעורים אלה משמשים לאכלוס א מיכל שעועית לְהִתְנַגֵד:

מחלקה ציבורית BeanContainer {שעועית רשימה פרטית; // גטר וקובע}

אנו יכולים לראות כי תקציר שעועית הערה עם הכיתה @JsonTypeIdResolver, המציין שהוא משתמש בהתאמה אישית TypeIdResolver להחליט כיצד לכלול מידע בתת-סוג בסידרה וכיצד להשתמש במטא נתונים ההפך.

הנה מחלקת הפותרים לטיפול בהכללת מידע מסוג:

מחלקה ציבורית BeanIdResolver מרחיב את TypeIdResolverBase {פרטי JavaType superType; @Override init חלל ציבורי (JavaType baseType) {superType = baseType; } @ עקוף מזהה ציבורי getMechanism () {החזר Id.NAME; } @Override ציבורי מחרוזת idFromValue (אובייקט אובייקט) {להחזיר idFromValueAndType (obj, obj.getClass ()); } @Override ציבורי מחרוזת idFromValueAndType (אובייקט אובייקט, תת סוג סוג) {String typeId = null; החלף (subType.getSimpleName ()) {מקרה "FirstBean": typeId = "bean1"; לשבור; מקרה "LastBean": typeId = "bean2"; } להחזיר typeId; } @Override ציבורי JavaType typeFromId (הקשר DatabindContext, מזהה מחרוזת) {Class SubType = null; switch (id) {case "bean1": subType = FirstBean.class; לשבור; מקרה "bean2": subType = LastBean.class; } להחזיר context.constructSpecializedType (superType, subType); }}

שתי השיטות הבולטות ביותר הן idFromValueAndType ו typeFromId, כאשר הראשון אומר את הדרך לכלול מידע סוג בעת סדרת POJOs והאחרון קובע את תת-הסוגים של אובייקטים שנוצרו מחדש באמצעות מטא-נתונים אלה.

על מנת לוודא שגם סדרת ההפעלה וגם הסרת העריכה פועלות היטב, בואו נכתוב מבחן לאימות ההתקדמות המלאה.

ראשית, עלינו ליצור מיכל שעועית ושיעורי שעועית, ואז לאכלס את המיכל במופעי שעועית:

FirstBean שעועית 1 = חדש FirstBean (1, "שעועית 1"); LastBean bean2 = LastBean new (2, "שעועית 2"); שעועית רשימה = ArrayList חדש (); שעועית. להוסיף (שעועית 1); שעועית. להוסיף (שעועית 2); BeanContainer serializedContainer = שעועית חדשה (); serializedContainer.setBeans (שעועית);

לאחר מכן, מיכל שעועית האובייקט מסדרתי ואנו מאשרים שהמחרוזת המתקבלת מכילה מידע על סוג:

מחרוזת jsonString = mapper.writeValueAsString (serializedContainer); assertThat (jsonString, containString ("bean1")); assertThat (jsonString, containString ("bean2"));

פלט הסידור מוצג להלן:

{"שעועית": [{"@type": "bean1", "id": 1, "firstName": "שעועית 1"}, {"@type": "bean2", "id": 2, "lastName ":" שעועית 2 "}]}

מבנה JSON זה ישמש ליצירה מחדש של אובייקטים מאותם תת-סוגים לפני הסידור. להלן שלבי ההטמעה להתערבות:

BeanContainer deserializedContainer = mapper.readValue (jsonString, BeanContainer.class); רשימה beanList = deserializedContainer.getBeans (); assertThat (beanList.get (0), instanceOf (FirstBean.class)); assertThat (beanList.get (1), instanceOf (LastBean.class));

9. מסקנה

הדרכה זו הסבירה בפירוט כמה הערות ג'קסון פחות נפוצות. ניתן למצוא את היישום של דוגמאות וקטעי קוד בפרויקט GitHub.


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