چرا json انتخاب مناسبی برای API نیست

یه تکنولژی که چندین سال هست جای خودش رو باز کرده JSON API هست که عموما هم با REST API در کنار هم قرار می گیرن. تو این پست خیلی دوست دارم در این مورد با هم صحبت کنیم. پست ممکنه طولانی شه واسه همین کم کم می نویسم. :stuck_out_tongue:

JSON فرمتی هست که شاید به چشم انسان خوب و خونا بیاد اما از دید ماشین بسیار بد، بدون قانون و نسبتا سنگین هست. عدم وجود تایپ و schema برای داده ها (‌یه سری کتابخونه برای این کار هست که در مقایسه با فرمت های دیگه چنگی به دل نمی زنن) جزء بزرگترین مشکلات json هستند. برای مثال json چیزی در باره تاریخ نمی دونه واسه همین شما مجبورین تاریخ رو به صورت string در json ذخیره کنید. با این کار شما validation روی تاریخ رو از دست می دید و ممکن هست هر سرویس به روش خودش تاریخ رو ذخیره کنه و غیره …

یه مشکل دیگه ای که json داره حجم زیادش هست. ( البته در مقایسه با فرمت های قدیمی مثل XML خیلی سبک تر هست) فرض کنید یک لیست با ۵۰ تا hashmap رو که هر کدوم ۱۰ تا کلید ثابت دارند رو تو فرمت json بخواید جا بجا کنین. شما مجموعا برای هر کلید ۵۰ تا تکرار دارید و در کل ۵۰۰ بار تکرار ( می دونم اعداد و اینها باهم جور در نمیاد اما فکر می کنم منظور رو رسونده باشم.) این همه تکرار حجم json رو بالا می بره اونم با دیتا ای که شما نیازی بهش ندارید.

اینا یه سری از بدی های json بودن که به نظر من به اندازه ای هست که باعث شه ازش برای جابجایی یا ذخیره دیتا استفاده نکنیم. حداقل هر جایی که ارتباط ماشین با ماشین هست.

تنهای خوبی json اینه که توی browser به صورت native ساپورت می شه و نیاز به کتابخونه اضافی برای پردازشش نیست.

اما جایگزین های json چه چیزایی هستند؟
بشتگی به کاربرد داره اما در حالت کلی:

  • Avro
  • Protocol Buffers
  • Thrift
  • Transit
  • EDN
13 Likes

من بیشتر بدی جیسون و رست رو توی ایجاد کردن err و stateکدهاش میدونستم … چون ما مجبوریم از http status ها استفاده کنیم … مثلا از 404 یا 403 یا 401 و… .
ک میتونن علت هایی مثل نبودن یه api و داون بودن یه سرویس تو سرور و یا یه مشکل حاد رو شامل بشن … یا اینکه (کاری ک من کردم) همه استیت هارو به 200تغییر بدیم … و توی 200 با فرمت جیسون … این استیت کد هارو برگردونیم …

راه حل جایگزین ک برای داک بندی و حل این مشکل هست json rpc هست …
به نظرم rpc و grpc ک بصورت باینری اطلاعات رو ردو بدل میکنن فوق العاده هستن … ولی بیشتر برای ارتباط بین میکروسرویسا کاربردی هستن … و بصورت نیتیو تو مرورگر پشتیبانی نمیشه … و باید کتابخونه استفاده کرد . …

به نظر میاد فعلا چاره ای جز جیسون نداریم :smile:
البته تایپ تو جیسون … و ولیدیشن … با استانداردی مثل json schema ک بصورت لایبرری تو انواع زبونا بوجود اومده میشه انجام داد …

در کل من json schema رو خیلی میپسندم …

درباره این جایگزین ها هم زیاد اطلاع نداشتم . …

2 Likes

از بین چه گزینه هایی انتخاب مناسبی نیست؟
پایان متنو ندیدم،‌ اما بنظر نمیاد json همیشه آخرین گزینه باشه بخصوص وقتی با مرورگر و js سر و کار داریم اما خب متاسفانه ضعف های زیادی هم داره که شما فرمودین.

1 Likes

با درود خدمت دوستان لطفا توضیح بدهید کدا فعلنه بهتر از json api می باشد ؟ شما کدوم رو پیشنهاد می کنید و چرا ؟

عنوان رو که ابهام انگیز بود اصلاح کردم.

به نظر من تنها نکته مثبتش همین هست.

بستگی به مورد استفادت داره اما Avro بسیار عالی هست مخصوصا برای API ی که بین سرویس ها هست. اگر مجبورین json استفاده کنید transit می تونه یه سری از مشکلاتش رو حل کنه براتون

3 Likes

چندی پیش برای انجام کاری مطالعه ای روی این قضیه داشتم چون هیچ کدوم از دوستان نامی از graphql نبردن . مسلما نمیشه گفت بهتره یا اینطور چیزی ولی توی بعضی از یوز کیس ها میتونه بهترین نتیجه رو بهمون بده

Describe your data

type Project {
  name: String
  tagline: String
  contributors: [User]
}

Ask for what you want

{
  project(name: "GraphQL") {
    tagline
  }
}

Get predictable results

{
  "project": {
    "tagline": "A query language for APIs"
  }
}

GraphQL خیلی خیلی از json بهتره اما همچنان یه سری از مشکلات اصلی json رو داره.

اینم بهش اضافه کرد که گرچه مشکلات json رو به همراه داره ولی مزیت های خوبی ام داره مثل fetch کردن کلی در یک request


1 Likes

بله ۱۰۰٪ به مراتب از json API بهتر هستش.

1 Likes

تو عمل هنوز ازش استفاده نکردم روی کاغذ خوبتر به نظر میاد ولی باید تو عمل دید تا چه حد میتونه حرفی برای گفتن داشته باشه

https://www.techiediaries.com/django-graphql-tutorial/

GraphQL زیاد برای استفاده در اپلیکشن های monolithic مناسب نیست.

1 Likes

درود سمیر جان می شه در این مورد یکمی توضیح بیشتر بدید ؟

1 Likes

تو اپ های monolithic مخصوصا اون هایی که با یه فریم ورک MVC چیزی ساخته شدن استفاده از GraphQL باعث می شه که هر کوئری GraphQL مپ بشه به یه مدل یا یه کوئری خواص به همین دلیل مثلا شما اگه ۱۰ تا پست آخر رو با کامنت هاشون بخواین باید ۲ تا کوئری بزنین ( یا در بهترین حالت بجای expose کردن دوتا فانکشن برای پست و کامنت یه فانکشن جدید می سازید برای همین منظور که با گسترش پروژه تعداد اینجور فانکشن ها هم بیشتر می شن و پیچیدگی الکی به نرم افزار اضافه می کنه) این موضوع برای کاربرد های پیچیده تر بیشتر خودشو نشون می ده که باعث کاهش پرفرمنس سیستم میشه. خیلی ها اومدن و تلاش کردن به نوعی این مشکل رو حل کنن. اما مشکل اصلی ساختار اپ اصلی هست.

اما اگر از یه سیستم reactive یا هر مدل مدرن دیگه استفاده بشه هر بخش از کوئری کلی رو یه قسمتی از سیستم هندل می کنه و دیگه چندتا دینابیس کوئری از لحاظ پرفرمنس تاثیری ندارن. البته از لحاظ هزینه متفاوتن اما خوب اپ های Monolithic برای کار های کوچیک مناسبن.

2 Likes

این مقاله رو یه نگاه بنداز :wink:

1 Likes

یکی از مزیت‌های JSON که باعث شده در REST API استفاده بشه؛‌ نداشتن Tight Coupling و Type هست. روی فیلدینگ توی یکی از مقاله‌هاش به این اشاره کرده:

http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven

A REST API should never have “typed” resources that are significant to the client. Specification authors may use resource types for describing server implementation behind the interface, but those types must be irrelevant and invisible to the client. The only types that are significant to a client are the current representation’s media type and standardized relation names.

و اینکه معمولا این جایگزین‌ها اصطلاحا خود-توضیح نیستند؛‌ حتی خود گوگل هم در مورد Protocol Buffers به این اشاره کرده:

“Protocol Buffers do not contain descriptions of their own types. Thus, given only a raw message without the corresponding .proto file defining its type, it is difficult to extract any useful data.”

و کلا JSON برای این محبوب هست که stateless محسوب میشه و coupling ایجاد نمیکنه؛‌ در صورتی که بقیه جایگزین‌های دارای type اگر نیاز باشه جایی ازشون استفاده بشه باید reference بشن حالا چه به صورت یک git submodule یا دوباره نویسی و اصطلاحا مشکلات maintain و sync بودن رو به همراه دارند و در مورد تست نویسی هم این مورد صدق میکنه؛ برای مثال: برای تست یک APIای که از Protocol Buffers استفاده میکنه حتما باید schemaی اون API اصطلاحا mock بشه یا عینا همون فرمت با داده‌های fake پر بشه.

و اینکه بیشتر این جایگزین ها برای لینک کردن به resource های بعد (برای مثال pagination یا detail یک resource) استاندارد خاصی وجود نداره و معمولا کلک‌های دیگه‌ای زده میشه.

دقیقا این مشکل json هست نه نکته مثبتش. برای مثال هر سرویس می تونه بجای فیلدی که باید زمان رو نگه داره هرچیزی قرار بده. و این می تونه به راحتی مشکلات زیادی رو بود بیاره. ProtoBuf خودش شماشو با خودش نداره اما json کلا شما نداره.
بجاش می تونین Avro استفاده کنین که قابلیت این رو داره که شما رو با خودش حمل کنه.

بین چه چیزهایی ؟

این در صورتی هست که تا حالا ازشون استفاده نگرده باشین و مثلا ProtoBuf استفاده کنین و Schema Registry نداشته باشین. در مورد Avro هیچکدوم از اینها درست نیست.

json هم نداره. شما برای این کار از header های HTTP استفاده می کننین که کاری به فرمت نداره مثلا هدر Location

avro من استفاده نکردم؛‌ به نظرم جالبه. ولی بیشتر مواردی که من گفتم در رابطه با تجربهٔ من با Protocol Buffers بوده.

فکر کنم دقیقا نقطه قوت JSON نداشتن شِماست. چون توی مثال لینک کردن شما به راحتی میتونی یک کلید رو به API بعدی اختصاص بدی که resource بعدی یا metadata اشاره میکنه.

ProtoBuff هم می تونین Schema Registry داشته باشین. از همه مهم تر اینه که مشتری باهاتون تماس می گیره میگه API اون جوری که گفتین کار نمی کنه سرویستون باگ داره برسی می کننین آخر سر معلوم می شه مشتری از دیتا json شما اشتباه استفاده کرده و …

اما مثلا حتی در مورد ProtoBuff اگر schema رو بگیره و استفاده کنه ۱۰۰٪ دیتا ای رو به اون صورتی می گیره که شما انتظار دارین.

فکر میکنم استفادهٔ‌ اشتباه از API تا حدودی به ضعف مستندسازی هم مربوط میشه و حتما به JSON ختم نمیشه. و اینکه Schema Registry هم یک complexity محسوب میشه داخل سیستم و باز هم maintainability افزایش پیدا میکنه البته به نظر من.

مستندات جای خودشون رو دارن. اما وقتی شما هر دیتا رو به دنیای خارج از نرم افزارتون می فرستین. یا از دنیای خارج می گیرین باید جلوی این رو بگیرید که کاربر از اون دیتا هر برداشتی خواست رو داشته باشه.

در مورد Schema Registry هم باید بگم complexity نیست چون ۹۹٪ مواقع شما اصلا باهاش کاری ندارین و جزء پروتوکلی هست که استفاده می کنین یا جزء از build process هست. اما خوب باید Maintain بشه مثل هر نرم افزار دیگه ای. البته اگر Avro استفاده بشه و schema رو با خودش توزیع کنین نیاز به این کار نیست کلا.

1 Likes