آموزشدانستنی‌ها

JSON با Jackson، (بخش سوم) Tree Model

نوشته‌ی حاضر به Tree Model می‌پردازد که یکی از سه روش تولید و خواندن JSON با بسته‌ی‌ نرم‌افزاری Jackson است. همانند مقاله‌ی قبلی مثالی را با این روش بررسی کرده و در انتها به این سوال می‌پردازیم: «در چه مواردی این متد را بر دو رقیب دیگر ترجیح دهیم؟»

در مقاله‌ی اول پس از معرفی بسته‌ی نرم‌افزاری Jackson یک مثال با روش Data Binding بررسی کردیم و در مقاله‌ی دوم روش Stream Method معرفی شد، سومین روش یا Tree Model در ادامه شرح داده می‌شود.

تولید JSON در Tree Model

روش کار در Tree Model به این صورت است که ابتدا یک شی از ObjectNode به عنوان «شی ریشه» یا «root object» ساخته می‌شود. شی ریشه معادل کلاس اصلی در JSON است. در ادامه مقادیر key/value را به ریشه ملحق می‌کنیم. برای این کار از نسخه‌های مختلف متد put یا set از کلاس ObjectNode استفاده خواهیم کرد. برای حاصل کردن objectNode دو روش وجود دارد:

  • روش اول: ساخت یک شی ObjectMapper و استفاده از متد createObjectNode آن.
  • روش دوم: ساخت یک شی JsonNodeFactory و استفاده از متد objectNode آن.
در تکه کد زیر از روش دوم استفاده شده است.
هنگام ساخت شیء‌ریشه، با استفاده از متد‌های زیر key/Value های JSON را ساخته و به آن اضافه کردیم. value می‌تواند مقادیر ساده (رشته یا عدد) یا مقادیر مرکب (مانند شی JSON یا آرایه) باشد. از لیست زیر دو متد set و setAll برای مواردی است که نوع value یکی از موارد مرکب باشد. در این صورت ابتدا شیء‌ای از ObjectNode یا ArrayNode را ساخته و سپس روی شیء ریشه، الصاق می‌کنیم.
VariableType در شبه کد فوق می‌تواند یکی از موارد زیر باشد:

BigDecimal, BigInteger, boolean, Boolean, byte[], double, float, int, long, short, String

شکل زیر ساختار کلاس‌های API و نسبت JsonNode را با ObjectNode و ArrayNode نشان می‌دهد.

تکه کد زیر نشان می‌دهد پس از ساختن «شیء‌ریشه»، نوشتن متن JSON ای تولید شده در یک فایل چگونه انجام می‌شود.

از یکی از متد‌های زیر، که از کلاس ObjectMapper هستند، استفاده کرده‌ایم:

اجازه دهید از تفاوت‌های دو متد عبور کنیم و تنها به این نکته اشاره‌ داشته باشیم که TreeNode interface توسط JsonNode پیاده‌سازی شده و تفاوت فاحشی بین دو متد بالا نیست.

JsonGenerator نیز، کلاس آشنایی است. چرا که در مقاله‌ی قبل برای تولید JSON با Stream Method از آن استفاده کردیم. به وسیله‌ی این کلاس مشخص می‌کنیم داده‌ای که تولید می‌کنیم «کجا» و با چه «Encoding»‌ای نوشته شود.

خواندن JSON در Tree Model

همان‌طور که در تولید JSON به روش Tree Model بخش زیادی از کار مربوط به ساختن «شیء ریشه» بود، در «خواندن» به این روش نیز، تمرکز کار روی به‌دست آوردن یک شیء ریشه از نوع JsonNode و سپس پیمایش (traverse) آن است.
برای به دست آوردن root JsonNode دو روش وجود دارد:

  • روش اول: استفاده از یکی از نسخه های overload شده‌ی متد زیر از کلاس ObjectMapper که می‌تواند داده‌ی JSON را از یکی از منابع بخواند و یک شیء از نوع JsonNode برگرداند.

SourceType در شبه کد فوق می‌تواند یکی از موارد زیر باشد:

byte[] , File, InputStream, JsonParser, Reader, String, URL

  • روش دوم: استفاده از یکی از نسخه‌های overload شده‌ی متد زیر از کلاس ObjectMapper که پارامتر اول آن، نوع منبع را معرفی کرده و پارامتر دوم از نوع Class است. با تنظیم پارامتر دوم به JsonNode.class خروجی مطلوب حاصل می‌شود.

SourceType در شبه کد فوق می‌تواند یکی از موارد زیر باشد:

byte[] , File, InputStream, JsonParser, Reader, String, URL  AND DataInput

در مثال زیر با استفاده از روش اول یک root JsonNode را از یک فایل به دست می‌آوریم:

حال باید بتوانیم به فیلد‌های شیء‌ریشه دسترسی پیدا کنیم. متد‌های زیر در JsonNode به این منظور ارائه شده‌اند.

توضیحمتد
برای آرایه‌ها، المان موجود در index را برمی‌گرداند. شروع شمارش از صفر است. اگر المان با شماره‌ی index در دسترس نباشد یکی از موارد زیر اتفاق می‌افتد:

  • اگر index خارج از محدوده‌ی مناسب برای آرایه باشد (یعنی کوچکتر از صفر یا بزرگتر از اندازه ی آرایه باشد)، null برمی‌گرداند.
  • اگر value مربوط به این فیلد از نوع ArrayNode نباشد، null برمی‌گرداند.
  • اگر value مربوط به این فیلد از نوع null باشد، مقداری که برگردانده می‌شود از نوع NullNode خواهد بود، نه از نوع null جاوا.
JsonNode get(int index)
برای Object ها مقدار فیلدی که نام آن property باشد را بر می‌گرداند. اگر :

  • فیلدی با این نام وجود نداشته باشد null برمی‌گرداند.
  • اگر value مربوط به این فیلد از نوع ObjectNode نباشد، null بر می‌گرداند.
  • اگر value مربوط به این فیلد از نوع null باشد، مقداری که برگردانده می‌شود از نوع NullNode خواهد بود. نه از نوع null جاوا.
JsonNode get(String property)
مشابه متد‌های get در ردیف‌های فوق، با این تفاوت که به جای null جاوا در موارد گفته شده، شیء‌ای از نوع MissingNode بر‌می‌گرداند.JsonNode path(int index) JsonNode path(String property)
  • در صورتی که این متد روی فیلدی اجرا شود که value آن از نوع Object باشد JsonNode حاوی آن Object را برمی‌گرداند.
  • در صورتی که فیلدی به این نام وجود نداشته باشد، فیلدی از نوع Object ساخته می‌شود، به شیء اضافه می‌شود و سپس برگردانده می‌شود.
  • در صورتی که این متد روی فیلدی اجرا شود که value آن از نوع Object نباشد UnsupportedOperationException پرتاب می‌شود.
JsonNode with(String propertyName)
  • در صورتی که این متد روی فیلدی اجرا شود که value آن از نوع Array باشد آن را برمی‌گرداند.
  • در صورتی که فیلدی به این نام وجود نداشته باشد، فیلدی از نوع Array ساخته می‌شود، به شیء اضافه می‌شود و سپس برگردانده می‌شود.
  • در صورتی که این متد روی فیلدی اجرا شود که value آن از نوع Array نباشد UnsupportedOperationException پرتاب می‌شود.
JsonNode withArray(String propertyName)

پس از اینکه فیلد را در قالب JsonNode به دست آوردیم، می‌توانیم از متد‌های زیر استفاده کنیم تا مقدار value آن را مشاهده کنیم.

  • متد‌های سری XXXvalue : (مانند intValue) این متد‌ها برای استخراج مقدار به کار می‌روند، در مواردی که نوع آن را به طور دقیق می‌دانیم.
  • متدهای سری asXXX: (مانند asInt) این متد‌ها برای تبدیل و استخراج مقدار به کار می‌روند. صرف نظر از نوع ذخیره‌ی داده در JSON آن را به نوع دلخواه ما تغییر می‌دهد (اگر تغییر ممکن باشد، مانند تبدیل قابل قبول int به String).

در مثال زیر از متد‌هایی که توضیح داده شد، برای استخراج داده از JSON و ساختن یک Employee استفاده شده است.

پیمایش JSON در Tree Model

در مثال فوق بخش مهمی از متد‌های Tree Model را برای به دست آوردن فیلد‌های JSON دیدیم. استفاده از تمام متد‌های فوق مستلزم دانستن نام فیلد داده هستند. اما اگر یک داده‌ی JSON ای در اختیار ما قرار گیرد و در مورد ساختار و فیلد‌های آن هیچ اطلاعی نداشته باشیم چگونه باید آن را پیمایش کرده و اطلاعات مورد نیاز را استخراج کنیم؟

Tree Model برای چنین مواردی متدهایی را در اختیار قرار داده است. از جمله:

به عنوان مثال اگر شکل JSON ای که در قسمت‌های قبلی برای یک شی از کلاس Employee ساخته‌ایم را دریافت کرده و شیء‌ریشه‌ی آن را به عنوان ورودی به متد زیر بدهیم می‌توانیم فیلد‌های آن را پیمایش کرده و در مورد هر فیلد نام و نوع value را به دست آورده و چاپ کنیم.

خروجی اجرای تکه کد فوق به این صورت است:

ویژگی Tree Model

عمده‌ی استفاده این روش زمانی است که بین کلاس‌های پروژه یک POJO معادل JSON نداریم، چرا که اگر یک کلاس معادل JSON وجود داشته باشد بهترین و به صرفه‌ترین متد استخراج داده از آن، استفاده از Data Binding است. در مواردی که داده‌ای در اختیارمان قرار‌گرفته و در مورد محتوا، نام فیلد‌ها، نوع Value فیلد‌ها و… هیچ اطلاعی نداریم، متد‌های پیمایش Tree Model راهگشا‌ خواهند بود.

این روش، آشناترین شکل از داده برای برنامه‌نویسانی است که با فرمت XML کار کرده‌اند، چرا که در سطح مفهومی، ساختار درختیِ اشیاء JSON بسیار مشابه مفهوم DOM در فضای XML است.

بخش چهارم-الف

.

.

.

با ما همراه باشید

آدرس کانال تلگرام: JavaCupIR@

آدرس اکانت توییتر: JavaCupIR@

آدرس صفحه اینستاگرام: javacup.ir

آدرس گروه لینکدین: Iranian Java Developers

[تعداد: 1    میانگین: 5/5]
برچسب ها
نمایش بیشتر

نوشته های مشابه

پاسخی بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا