रेस्टफुल एपीआई से पेजेशन प्रतिक्रिया पेलोड


84

मैं अपने RESTful API में पेजिनेशन का समर्थन करना चाहता हूं।

मेरी एपीआई विधि के माध्यम से उत्पाद की JSON सूची वापस आनी चाहिए /products/index। हालाँकि, संभावित रूप से हजारों उत्पाद हैं, और मैं उनके माध्यम से पेज करना चाहता हूं, इसलिए मेरा अनुरोध कुछ इस तरह दिखना चाहिए:

/products/index?page_number=5&page_size=20

लेकिन मेरे JSON की प्रतिक्रिया को क्या देखना चाहिए? क्या एपीआई उपभोक्ता आमतौर पर प्रतिक्रिया में पेजेशन मेटा डेटा की उम्मीद करेंगे? या केवल उत्पादों की एक सरणी आवश्यक है? क्यों?

ऐसा लगता है कि ट्विटर के एपीआई में मेटा डेटा: https://dev.twitter.com/docs/api/1/get/lists/members (उदाहरण अनुरोध देखें) शामिल हैं।

मेटा डेटा के साथ:

{
  "page_number": 5,
  "page_size": 20,
  "total_record_count": 521,
  "records": [
    {
      "id": 1,
      "name": "Widget #1"
    },
    {
      "id": 2,
      "name": "Widget #2"
    },
    {
      "id": 3,
      "name": "Widget #3"
    }
  ]
}

उत्पादों की सिर्फ एक सरणी (कोई मेटा डेटा नहीं):

[
  {
    "id": 1,
    "name": "Widget #1"
  },
  {
    "id": 2,
    "name": "Widget #2"
  },
  {
    "id": 3,
    "name": "Widget #3"
  }
]

जवाबों:


110

रेस्टफुल एपीआई का मुख्य रूप से अन्य प्रणालियों द्वारा सेवन किया जाता है, यही वजह है कि मैंने रिस्पॉन्स हेडर में पेजिंग डेटा डाला। हालाँकि, कुछ API उपभोक्ताओं के पास प्रतिक्रिया शीर्षलेखों तक सीधी पहुँच नहीं हो सकती है, या आपके API पर UX का निर्माण हो सकता है, इसलिए JSON प्रतिक्रिया में मेटाडेटा को पुनः प्राप्त करने (मांगने) का एक तरीका प्रदान करना एक प्लस है।

मेरा मानना ​​है कि आपके कार्यान्वयन में अनुरोध के अनुसार मशीन-पठनीय मेटाडेटा और डिफ़ॉल्ट रूप से मानव-पठनीय मेटाडेटा शामिल होना चाहिए। मानव-पठनीय मेटाडेटा को हर अनुरोध के साथ वापस किया जा सकता है यदि आप पसंद करते हैं या, अधिमानतः, ऑन-डिमांड एक क्वेरी पैरामीटर के माध्यम से, जैसे कि include=metadataया include_metadata=true

आपके विशेष परिदृश्य में, मैं रिकॉर्ड के साथ प्रत्येक उत्पाद के लिए यूआरआई शामिल करूंगा। यह एपीआई उपभोक्ता के लिए व्यक्तिगत उत्पादों के लिंक बनाना आसान बनाता है। मैं अपने पेजिंग अनुरोधों की सीमाओं के अनुसार कुछ उचित अपेक्षाएं भी निर्धारित करूंगा। पृष्ठ आकार के लिए डिफ़ॉल्ट सेटिंग्स को लागू करना और प्रलेखित करना एक स्वीकार्य अभ्यास है। उदाहरण के लिए, GitHub की एपीआई अधिकतम 100 के साथ 30 पेज के लिए डिफ़ॉल्ट पृष्ठ आकार सेट करती है, साथ ही साथ आप एपीआई को क्वेरी कर सकते हैं की संख्या पर एक दर सीमा निर्धारित करता है। यदि आपके एपीआई में एक डिफ़ॉल्ट पृष्ठ आकार है, तो क्वेरी स्ट्रिंग केवल पृष्ठ सूचकांक को निर्दिष्ट कर सकती है।

मानव-पठनीय परिदृश्य में, जब नेविगेट करने के लिए /products?page=5&per_page=20&include=metadata, प्रतिक्रिया हो सकती है:

{
  "_metadata": 
  {
      "page": 5,
      "per_page": 20,
      "page_count": 20,
      "total_count": 521,
      "Links": [
        {"self": "/products?page=5&per_page=20"},
        {"first": "/products?page=0&per_page=20"},
        {"previous": "/products?page=4&per_page=20"},
        {"next": "/products?page=6&per_page=20"},
        {"last": "/products?page=26&per_page=20"},
      ]
  },
  "records": [
    {
      "id": 1,
      "name": "Widget #1",
      "uri": "/products/1"
    },
    {
      "id": 2,
      "name": "Widget #2",
      "uri": "/products/2"
    },
    {
      "id": 3,
      "name": "Widget #3",
      "uri": "/products/3"
    }
  ]
}

मशीन-पठनीय मेटाडेटा के लिए, मैं प्रतिक्रिया के लिए लिंक हेडर जोड़ूंगा :

Link: </products?page=5&perPage=20>;rel=self,</products?page=0&perPage=20>;rel=first,</products?page=4&perPage=20>;rel=previous,</products?page=6&perPage=20>;rel=next,</products?page=26&perPage=20>;rel=last

(लिंक शीर्षक मान urlencoded होना चाहिए)

... और संभवतः एक कस्टम total-countप्रतिक्रिया हेडर, यदि आप ऐसा चुनते हैं:

total-count: 521

मानव-केंद्रित मेटाडेटा में सामने आए अन्य पेजिंग डेटा मशीन-केंद्रित मेटाडेटा के लिए अति-उपयोगी हो सकते हैं, क्योंकि लिंक हेडर मुझे यह बताते हैं कि मैं किस पृष्ठ पर हूं और प्रति पृष्ठ संख्या, और मैं सरणी में रिकॉर्ड की संख्या को तुरंत प्राप्त कर सकता हूं। । इसलिए, मैं शायद कुल गिनती के लिए एक हेडर बनाऊंगा। आप हमेशा बाद में अपना विचार बदल सकते हैं और अधिक मेटाडेटा जोड़ सकते हैं।

एक तरफ के रूप में, आप नोटिस कर सकते हैं मैं /indexअपने यूआरआई से हटा दिया । एक आम तौर पर स्वीकार किए गए सम्मेलन में आपके ReST समापन बिंदु संग्रह को उजागर करना है। /indexअंत muddies कि थोड़ा ऊपर होने के बाद ।

API का उपभोग / निर्माण करते समय ये कुछ चीजें हैं जो मुझे पसंद हैं। उम्मीद है की वो मदद करदे!


per_page कन्वेंशन पेज का अनुसरण नहीं करता है_साइज़
अलेक्जेंड्रोस

1
"page_count": 20और {"last": "/products?page=26&per_page=20"}?
जेरेम

1
यदि पृष्ठ 1 से पृष्ठ x तक के सभी रिकॉर्ड प्राप्त करते समय उत्पाद की संख्या अचानक बढ़ जाती है तो क्या होगा?
MeV

3
@MeV वही होता है जो किसी भी कर्सर-आधारित पेजिनेशन परिदृश्य पर होता है: कुल में वृद्धि होगी, और पृष्ठ संख्या बढ़ सकती है यदि अंतिम पृष्ठ भरा हुआ है, और कुछ नहीं, कुछ कम नहीं। यह प्रत्येक ऐप पर एक बहुत ही सामान्य परिदृश्य है जो इस प्रकार के पृष्ठांकन का उपयोग करता है। यह उस छंटाई पर निर्भर करेगा जिसका उपयोग किया जा रहा है यदि नया उत्पाद पहले या अंतिम पृष्ठ पर दिखाई देता है।
पाब्लो पज़ोस

2
"रेस्टफुल एपीआई का उपयोग मुख्य रूप से अन्य प्रणालियों द्वारा किया जाता है, यही वजह है कि मैंने रिस्पॉन्स हेडर में पेजिंग डेटा डाल दिया है" यह कहना है कि यह बाहर धूप है, यही कारण है कि मैं नीली शर्ट पहन रहा हूं। आपको क्या लगता है कि हेडर मनुष्यों द्वारा नहीं पढ़ा जा सकता है?
एक बेहतर जैतून

29

जैसा कि किसी ने REST सेवाओं का उपभोग करने के लिए कई पुस्तकालयों को लिखा है, मैं आपको ग्राहक का दृष्टिकोण बताता हूं कि मुझे क्यों लगता है कि मेटाडेटा में परिणाम लपेटने का तरीका है:

  • कुल गिनती के बिना, क्लाइंट को कैसे पता चल सकता है कि उसने अभी तक सब कुछ प्राप्त नहीं किया है और परिणाम सेट के माध्यम से पेजिंग जारी रखना चाहिए? एक यूआई में जो अगले पृष्ठ पर आगे नहीं दिखता है, सबसे खराब स्थिति में इसे एक अगले / अधिक लिंक के रूप में दर्शाया जा सकता है जो वास्तव में कोई और डेटा प्राप्त नहीं करता था।
  • प्रतिक्रिया में मेटाडेटा शामिल करने से ग्राहक को कम स्थिति ट्रैक करने की अनुमति मिलती है। अब मुझे प्रतिक्रिया के साथ अपने REST अनुरोध का मिलान नहीं करना है, क्योंकि प्रतिक्रिया में अनुरोध स्थिति (इस मामले में डेटासेट में कर्सर) को फिर से संगठित करने के लिए मेटाडेटा आवश्यक है।
  • यदि राज्य प्रतिक्रिया का हिस्सा है, तो मैं एक ही डाटासेट में कई अनुरोधों को एक साथ कर सकता हूं, और मैं किसी भी क्रम में उन अनुरोधों को संभाल सकता हूं जो वे आने के लिए करते हैं जिसमें जरूरी नहीं कि जिस क्रम में मैंने अनुरोध किया था।

और एक सुझाव: ट्विटर एपीआई की तरह , आपको एक सीधे सूचकांक / कर्सर के साथ पेज_नंबर को बदलना चाहिए। इसका कारण है, एपीआई क्लाइंट को प्रति पेज साइज निर्धारित करने की अनुमति देता है। क्या ग्राहक द्वारा अब तक मांगे गए पेजों की संख्या लौटा दी गई है, या अंतिम उपयोग किए गए पेज_साइज को दिए गए पेज की संख्या (लगभग निश्चित रूप से बाद में, लेकिन पूरी तरह से ऐसी अस्पष्टता से क्यों न बचें)?


10
अपनी पहली बुलेट के लिए, क्या यह एक अगला पृष्ठ नहीं होने पर rel = अगली लिंक को छोड़ने के लिए एक उपयुक्त समाधान होगा? आपकी दूसरी बुलेट के लिए, जानकारी अभी भी क्लाइंट की प्रतिक्रिया में उपलब्ध है, यह सिर्फ प्रतिक्रिया के शरीर में नहीं है, बल्कि हेडर में है। अपने अंतिम पैराग्राफ पर +1।
काइल हेस

मैं अंत में आपके सुझाव का जवाब देना चाहता हूं। कर्सर पृष्ठांकन पृष्ठ / ऑफ़सेट पृष्ठांकन के समान नहीं है। दोनों के पेशेवरों और विपक्ष और प्रदर्शन के विचार हैं।
kjonsson

19

मैं उसी के लिए हेडर जोड़ने की सलाह दूंगा। मेटाडेटा को हेडर में ले जाने से लिफाफे से छुटकारा पाने में मदद मिलती है result, dataया recordsप्रतिक्रिया शरीर में केवल वही डेटा होता है जिसकी हमें आवश्यकता होती है। यदि आप पेजेशन लिंक भी उत्पन्न करते हैं तो आप लिंक हेडर का उपयोग कर सकते हैं ।

    HTTP/1.1 200
    Pagination-Count: 100
    Pagination-Page: 5
    Pagination-Limit: 20
    Content-Type: application/json

    [
      {
        "id": 10,
        "name": "shirt",
        "color": "red",
        "price": "$23"
      },
      {
        "id": 11,
        "name": "shirt",
        "color": "blue",
        "price": "$25"
      }
    ]

जानकारी के लिए देखें:

https://github.com/adnan-kamili/rest-api-response-format

स्वैगर फ़ाइल के लिए:

https://github.com/adnan-kamili/swagger-response-template


3
RFC-6648 के अनुसार, "X-" उपसर्ग को मेटाडेटा कुंजी में छोड़ दिया जाना चाहिए।
रे

1
@RayKoopa धन्यवाद, मैंने github पेज अपडेट किया था लेकिन इस जवाब को अपडेट करना भूल गया।
अदनान कामिली

0

प्रतिक्रिया बॉडी में बस अपने बैकएंड एपीआई नई प्रॉपर्टी में जोड़ें। उदाहरण से। नेट कोर:

[Authorize]
[HttpGet]
public async Task<IActionResult> GetUsers([FromQuery]UserParams userParams)
{
  var users = await _repo.GetUsers(userParams);
  var usersToReturn = _mapper.Map<IEnumerable<UserForListDto>>(users);


  // create new object and add into it total count param etc
  var UsersListResult = new
  {
    usersToReturn,
    currentPage = users.CurrentPage,
    pageSize = users.PageSize,
    totalCount = users.TotalCount,
    totalPages = users.TotalPages
  };

  return Ok(UsersListResult);
}

शरीर की प्रतिक्रिया में यह इस तरह दिखता है

{
"usersToReturn": [
    {
        "userId": 1,
        "username": "nancycaldwell@conjurica.com",
        "firstName": "Joann",
        "lastName": "Wilson",
        "city": "Armstrong",
        "phoneNumber": "+1 (893) 515-2172"
    },
    {
        "userId": 2,
        "username": "zelmasheppard@conjurica.com",
        "firstName": "Booth",
        "lastName": "Drake",
        "city": "Franks",
        "phoneNumber": "+1 (800) 493-2168"
    }
],
// metadata to pars in client side
"currentPage": 1,
"pageSize": 2,
"totalCount": 87,
"totalPages": 44

}


-3

आम तौर पर, मैं साधारण तरीके से बनाता हूं, जो भी हो, मैं "लोकलहोस्ट / एपीआई / मेथड /: lastIdObtain /: countDateToReturn" उदाहरण के लिए एक रेस्टैप एंडपॉइंट बनाता हूं, जिसमें आप थिसिस मापदंडों को शामिल कर सकते हैं, आप इसे एक साधारण अनुरोध कर सकते हैं। सेवा में, उदाहरण के लिए; नेट

jsonData function(lastIdObtained,countDatetoReturn){
'... write your code as you wish..'
and into select query make a filter
select top countDatetoreturn tt.id,tt.desc
 from tbANyThing tt
where id > lastIdObtained
order by id
}

इओनिक में, जब मैं नीचे से ऊपर तक स्क्रॉल करता हूं, तो मैं शून्य मान पास करता हूं, जब मुझे उत्तर मिलता है, तो मुझे प्राप्त अंतिम आईडी का मूल्य निर्धारित होता है, और जब मैं ऊपर से नीचे स्लाइड करता हूं, तो मुझे अंतिम पंजीकरण आईडी पास होती है जो मुझे मिली

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.