開發者經常會面臨 API 變更帶來的問題,比如依賴的庫不再支持某些方法,或者默認語義發生變化導致舊行為被隱藏。JSON API 的穩定性和可維護性。
此外,JSON API 規范詳細規定了從響應格式到端點行為的方方面面,包括集合與數組的選擇、缺失記錄的 HTTP 響應代碼等。這些規定幫助開發者避免重復造輪子,將更多精力集中在功能實現上。
以下是一個基于 Grape 和 JSON API 的簡單實現示例:
# Gemfile
gem 'pg'
gem 'sequel-rails'
gem 'sequel_secure_password'
gem 'grape'
gem 'grape-jsonapi-resources'
gem 'jsonapi-resources'
# app/models/user.rb
class User < Sequel::Model
plugin :secure_password def validate
super
validates_presence [:email, :password_digest, :first_name, :last_name]
end
end# app/controllers/api/base.rb
module API
class Base < Grape::API
mount API::V1::Base
end
end# app/controllers/api/v1/base.rb
module API
module V1
class Base < Grape::API
mount API::V1::Users
end
end
end
以上代碼通過嵌套命名空間實現了 API 的版本化,結構清晰且易于擴展。
在 Grape 中,可以通過擴展 ActiveSupport::Concern 來設置默認的響應格式:
# app/controllers/concerns/api/v1/defaults.rb
module API
module V1
module Defaults
extend ActiveSupport::Concern
included do
version 'v1', using: :path
format :json
formatter :json, Grape::Formatter::JSONAPIResources
content_type :json, 'application/vnd.api+json' rescue_from Sequel::NoMatchingRow do |exception| params = env['api.endpoint'].params
record_not_found = JSONAPI::Exceptions::RecordNotFound.new(params[:id])
not_found = JSONAPI::ErrorsOperationResult.new(record_not_found.errors[0].code, record_not_found.errors)
error! not_found, 404
end
end
end
end
end
上述代碼中,included 方法設置了 API 的版本、響應格式以及內容類型。此外,針對 Sequel 在處理不存在記錄時返回 nil 的行為,我們通過捕獲 Sequel::NoMatchingRow 異常并返回 404 錯誤來符合 JSON API 的規范。
以下是用戶相關的端點定義,包括 GET 和 POST 請求:
# app/controllers/api/v1/users.rb
module API
module V1
class Users < Grape::API
include API::V1::Defaults
resource :users do
desc '返回所有用戶'
get do
users = User.all
render users
end desc '返回指定用戶'
params do
requires :id, type: Integer, desc: '用戶 ID'
end
route_param :id do
get do
user = User.with_pk!(params[:id])
render user
end
end desc '創建用戶'
params do
requires :email, type: String, desc: '新用戶郵箱'
requires :first_name, type: String, desc: '新用戶名'
requires :last_name, type: String, desc: '新用戶姓'
requires :password, type: String, desc: '新用戶密碼'
optional :password_confirmation, type: String, desc: '密碼確認'
end
post do
user = User.new(
email: params[:email],
first_name: params[:first_name],
last_name: params[:last_name],
password: params[:password],
password_confirmation: params[:password_confirmation]
)
user.save
end
end
end
end
end
通過上述代碼,我們定義了用戶的基本操作,包括獲取所有用戶、獲取指定用戶以及創建新用戶。
最后,在 routes.rb 文件中掛載 API:
# config/routes.rb
mount API::Base => '/api'
完成配置后,您可以通過 /api/v1/users/:id 訪問用戶端點,并獲得符合 JSON API 規范的響應。
通過 Grape 和 JSON API 的結合,您可以以較低的成本構建符合規范的 API。JSON API 的標準化設計不僅提升了開發效率,還減少了因規范不一致帶來的問題。通過本文的示例代碼,您可以快速上手并實現自己的 API 項目。
原文鏈接: https://www.hark.bz/blog/post/make-graperails-app-json-api-compliant-cheap-2/