שימוש אופציונלי עם ג'קסון

1. הקדמה

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

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

2. סקירה כללית על הבעיה

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

2.1. תלות של Maven

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

 com.fasterxml.jackson.core jackson-core 2.11.1 

2.2. חפץ הספר שלנו

ואז, בואו ניצור כיתה סֵפֶר, המכיל אחד רגיל ואחד אופציונאלי שדה:

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

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

2.3. סידור

עכשיו, בוא נקים א סֵפֶר:

ספר ספרים = ספר חדש (); book.setTitle ("אוליבר טוויסט"); book.setSubTitle (Optional.of ("התקדמות נער הקהילה"));

ולסיום, בואו ננסה לסדר אותו באמצעות ג'קסון ObjectMapper:

תוצאת מחרוזת = mapper.writeValueAsString (ספר);

נראה כי התפוקה של ה- אופציונאלי שדה, אינו מכיל את הערך שלו, אלא אובייקט JSON מקונן עם שדה שנקרא מתנה:

{"title": "אוליבר טוויסט", "subTitle": {"present": true}}

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

במקרה הזה, isPresent () הוא מבקר ציבורי ב אופציונאלי מעמד. פירוש הדבר שהוא יועבר בסידרה עם הערך של נָכוֹן אוֹ שֶׁקֶר, תלוי אם הוא ריק או לא. זו התנהגות ברירת המחדל של ג'קסון לסידור

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

2.4. התפטרות

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

@Test (צפוי = JsonMappingException.class) חלל ציבורי givenFieldWithValue_whenDeserializing_thenThrowException String bookJson = "{\" title \ ": \" אוליבר טוויסט \ ", \" subTitle \ ": \" foo \ "}"; תוצאת הספר = mapper.readValue (bookJson, Book.class); } 

בואו נראה את עקבות הערימה:

com.fasterxml.jackson.databind.JsonMappingException: לא ניתן לבנות מופע של java.util. אופציונלי: אין בניית טיעון מחרוזת / שיטת מפעל לביטול הערך ממחרוזת ('התקדמות נער הקהילה')

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

3. פיתרון

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

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

3.1. תלות ורישום של Maven

ראשית, בואו נוסיף את הגרסה האחרונה כתלות של Maven:

 com.fasterxml.jackson.datatype jackson-datatype-jdk8 2.9.6 

כעת, כל שעלינו לעשות הוא לרשום את המודול אצלנו ObjectMapper:

ממפה ObjectMapper = ObjectMapper חדש (); mapper.registerModule (חדש Jdk8Module ());

3.2. סידור

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

ספר ספרים = ספר חדש (); book.setTitle ("אוליבר טוויסט"); book.setSubTitle (Optional.of ("התקדמות נער הקהילה")); מחרוזת serializedBook = mapper.writeValueAsString (ספר); assertThat (מ- (serializedBook) .getString ("משנה כותרת")) .isEqualTo ("התקדמות נער הקהילה");

אם ננסה לסדר ספר ריק, הוא יישמר כ- ריק:

book.setSubTitle (Optional.empty ()); מחרוזת serializedBook = mapper.writeValueAsString (ספר); assertThat (מ- (serializedBook) .getString ("משנה כותרת")). isNull ();

3.3. התפטרות

עכשיו, בואו נחזור על המבחנים שלנו לניתוק עריקה. אם נקרא מחדש את הספר שלנו, נראה שלא נקבל עוד JsonMappingException:

ספר newbook = mapper.readValue (תוצאה, Book.class); assertThat (newBook.getSubTitle ()). isEqualTo (Optional.of ("התקדמות נער הקהילה"));

לסיום, בואו נחזור על המבחן שוב, הפעם עם ריק. נראה ששוב לא נקבל JsonMappingException, ולמעשה, יש ריק אופציונאלי:

assertThat (newBook.getSubTitle ()). isEqualTo (Optional.empty ());

4. מסקנה

הראינו כיצד לעקוף את הבעיה על ידי מינוף המודול JDK 8 DataTypes, והדגמנו כיצד הוא מאפשר לג'קסון לטפל בריק אופציונאלי כפי ש ריק, ומתנה אופציונאלי כשדה רגיל.

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


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