स्वैगर इनहेरिटेंस एंड कम्पोजिशन


82

मेरे "सरलीकृत" एपीआई में, सभी प्रतिक्रियाएं एक आधार "प्रतिक्रिया" वर्ग से ली गई हैं ( विरासत )। प्रतिक्रिया वर्ग मेटाडेटा से भरे एक हेडर से बना होता है, और शरीर जिसमें उपयोगकर्ता का मुख्य डेटा होता है, अनुरोध करता है। प्रतिक्रिया (JSON में) इस तरह रखी गई है कि सभी मेटाडेटा पहले "लेयर" पर हैं और बॉडी एक एकल विशेषता है जिसे "बॉडी" कहा जाता है जैसे

response
|--metadata attribute 1 (string/int/object)
|--metadata attribute 2 (string/int/object)
|--body (object)
    |--body attribute 1 (string/int/object)
    |--body attribute 2 (string/int/object)

मैंने निम्नलिखित JSON के साथ स्वैगर में इस संबंध को परिभाषित करने की कोशिश की है:

{
    ...
    "definitions": {
        "response": {
            "allOf": [
                {
                    "$ref": "#/definitions/response_header"
                },
                {
                    "properties": {
                        "body": {
                            "description": "The body of the response (not metadata)",
                            "schema": {
                                "$ref": "#/definitions/response_body"
                            }
                        }
                    }
                }
            ]
        },
        "response_header": {
            "type": "object",
            "required": [
                "result"
            ],
            "properties": {
                "result": {
                    "type": "string",
                    "description": "value of 'success', for a successful response, or 'error' if there is an error",
                    "enum": [
                        "error",
                        "success"
                    ]
                },
                "message": {
                    "type": "string",
                    "description": "A suitable error message if something went wrong."
                }
            }
        },
        "response_body": {
            "type": "object"
        }
    }
}

फिर मैं विभिन्न बॉडी / हेडर क्लासेस बनाकर अलग-अलग प्रतिक्रियाएँ बनाने की कोशिश करता हूँ जो बॉडी / हेडर से विरासत में मिलती हैं, और फिर बच्चे के रिस्पॉन्स क्लासेस बनाते हैं जो प्रासंगिक हेडर / बॉडी क्लासेस (नीचे सोर्स कोड में दिखाया गया है) से बना होता है। हालाँकि, मैं निश्चित हूं कि या तो यह काम करने का गलत तरीका है, या यह कि मेरा कार्यान्वयन गलत है। मैं स्वैगर 2.0 विनिर्देश (नीचे दिखाए गए) में वंशानुक्रम का एक उदाहरण खोजने में असमर्थ रहा हूं, लेकिन रचना का एक उदाहरण मिला है ।

यहाँ छवि विवरण दर्ज करें

मुझे पूरा यकीन है कि इस "विभेदकारी" के पास खेलने के लिए एक बड़ा हिस्सा है, लेकिन यह निश्चित नहीं है कि मुझे क्या करने की आवश्यकता है।

सवाल

क्या कोई मुझे दिखा सकता है कि स्वैगर 2.0 (JSON) में कंपोजीशन + इनहेरिटेंस लागू करने का तरीका कैसा है, अधिमानतः नीचे मेरा उदाहरण कोड "फिक्सिंग" करके। यह भी बहुत अच्छा होगा अगर मैं एक ErrorResponse वर्ग निर्दिष्ट कर सकता हूं जो प्रतिक्रिया से विरासत में मिलता है, जहां हेडर में "परिणाम" विशेषता हमेशा "त्रुटि" पर सेट होती है।

{
    "swagger": "2.0",
    "info": {
        "title": "Test API",
        "description": "Request data from the system.",
        "version": "1.0.0"
    },
    "host": "xxx.xxx.com",
    "schemes": [
        "https"
    ],
    "basePath": "/",
    "produces": [
        "application/json"
    ],
    "paths": {
        "/request_filename": {
            "post": {
                "summary": "Request Filename",
                "description": "Generates an appropriate filename for a given data request.",
                "responses": {
                    "200": {
                        "description": "A JSON response with the generated filename",
                        "schema": {
                            "$ref": "#/definitions/filename_response"
                        }
                    }
                }
            }
        }
    },
    "definitions": {
        "response": {
            "allOf": [
                {
                    "$ref": "#/definitions/response_header"
                },
                {
                    "properties": {
                        "body": {
                            "description": "The body of the response (not metadata)",
                            "schema": {
                                "$ref": "#/definitions/response_body"
                            }
                        }
                    }
                }
            ]
        },
        "response_header": {
            "type": "object",
            "required": [
                "result"
            ],
            "properties": {
                "result": {
                    "type": "string",
                    "description": "value of 'success', for a successful response, or 'error' if there is an error",
                    "enum": [
                        "error",
                        "success"
                    ]
                },
                "message": {
                    "type": "string",
                    "description": "A suitable error message if something went wrong."
                }
            }
        },
        "response_body": {
            "type": "object"
        },
        "filename_response": {
            "extends": "response",
            "allOf": [
                {
                    "$ref": "#definitions/response_header"
                },
                {
                    "properties": {
                        "body": {
                            "schema": {
                                "$ref": "#definitions/filename_response_body"
                            }
                        }
                    }
                }
            ]
        },
        "filename_response_body": {
            "extends": "#/definitions/response_body",
            "properties": {
                "filename": {
                    "type": "string",
                    "description": "The automatically generated filename"
                }
            }
        }
    }
}

आरेख अद्यतन

कोशिश करने और स्पष्ट करने के लिए कि मैं क्या चाहता हूं, मैंने नीचे बहुत ही मूल आरेख बनाया है, जिसका उद्देश्य यह बताना है कि सभी प्रतिक्रियाएं "प्रतिक्रिया" ऑब्जेक्ट की त्वरित प्रतिक्रियाएं हैं जो किसी भी प्रतिक्रिया_हाइडर और response_body वस्तुओं के संयोजन का उपयोग करके (रचना) द्वारा बनाई गई हैं। Response_header और response_body ऑब्जेक्ट्स को बढ़ाया जा सकता है और किसी भी प्रतिक्रिया ऑब्जेक्ट में डाला जा सकता है, जो कि एक filename_response के मामले में किया जाता है जो आधार response_body वर्ग के filename_response_body बच्चे का उपयोग करता है। त्रुटि और सफल प्रतिक्रिया दोनों "प्रतिक्रिया" ऑब्जेक्ट का उपयोग करते हैं।

यहाँ छवि विवरण दर्ज करें


1
वहाँ है रचना के लिए एक नमूना है, लेकिन यह यह साझा करने के लायक नहीं है इतना बुरा है। मैं इस बात पर काम करूंगा कि आपका चश्मा कैसा दिखना चाहिए। ध्यान रखें, यूआई वर्तमान में इसका समर्थन नहीं करता है, लेकिन यह तब होगा जब 2.0 के लिए पूर्ण समर्थन उपलब्ध है।
रॉन

1
और इससे पहले कि मैं गोता लगाऊं, एक और चीज - क्या आप रचना या विरासत की तलाश कर रहे हैं? रचना मूलतः कह रही है I have the properties of X and my own properties.। वंशानुक्रम एक संबंध का सुझाव देता हैX is my parent. I have its properties and my own. । वंशानुक्रम उपयोगी है यदि आप यह कहना चाहते हैं कि मॉडल का एक निश्चित सेट माता-पिता पर लागू होता है।
रॉन

1
मैं दोनों विरासत के उपयोग को प्रदर्शित करने की अपेक्षा कर रहा था इस उदाहरण के साथ एक बार में और रचना । जाहिर है मुझे एहसास है कि कोई भी आसानी से या तो खुद का उपयोग कर सकता है, लेकिन इस मामले में सभी प्रतिक्रियाएं आधार "प्रतिक्रिया" वर्ग के बच्चे हैं। और प्रतिक्रिया वर्ग दो अन्य वस्तुओं, हेडर और बॉडी की "रचना" है।
प्रोग्रामर

2
मैं स्पष्ट नहीं हो सकता है। वंशानुक्रम रचना का विस्तार है। अगर वहाँ विरासत है, वहाँ संरचना है। यदि रचना है, तो जरूरी नहीं कि विरासत हो। इसके अलावा, आपके नमूने में, "प्रतिक्रिया" मॉडल का कहीं भी उपयोग नहीं किया गया है। क्या मुझे इसे अनदेखा करना चाहिए और सिर्फ यह दिखाना चाहिए कि यह कैसे दिखना चाहिए?
रॉन

आह, विरासत और रचना के बीच उस रिश्ते का एहसास नहीं हुआ। इसलिए दोनों को दिखाने के लिए विरासत का उपयोग करें। प्रतिक्रिया मॉडल का उपयोग नहीं किए जाने के संबंध में, इसे फ़ाइल नाम_प्रतिपादक बच्चे में "विस्तारित" के साथ उपयोग किया जाना चाहिए, जिसके साथ अनुरोध प्रतिक्रिया करता है।
प्रोग्रामर

जवाबों:


114

स्वैगर में एक शुरुआत के रूप में, मैं बहुरूपता और रचना के बारे में आधिकारिक दस्तावेज को नहीं ढूंढता, जो आसान नहीं है, क्योंकि इसमें एक उदाहरण का अभाव है । जब मैंने नेट की खोज की थी, तो स्वैगर 1.2 के संदर्भ में बहुत सारे अच्छे उदाहरण हैं जोextends वैध थे।

के लिए अकड़ 2.0 मैं में एक अच्छा उदाहरण पाया GitHub पर अकड़ कल्पना स्रोतों इस के माध्यम से गूगल समूह

उपरोक्त स्रोतों के आधार पर, यहां YAML में एक छोटा वैध उत्तराधिकार उदाहरण दिया गया है:

definitions:
  Pet:
    discriminator: petType
    required:
      - name
      - petType # required for inheritance to work
    properties:
      name: 
        type: string
      petType:
        type: string
  Cat:
    allOf:
      - $ref: '#/definitions/Pet' # Cat has all properties of a Pet
      - properties: # extra properties only for cats
          huntingSkill:
            type: string
            default: lazy
            enum:
              - lazy
              - aggressive
  Dog:
    allOf:
      - $ref: '#/definitions/Pet' # Dog has all properties of a Pet
      - properties: # extra properties only for dogs
          packSize:
            description: The size of the pack the dog is from
            type: integer

वास्तव में धन्यवाद! यह मेरे लिए काम करता है। में editor.swagger.io, मुझे थोड़ा बग दिखाई देता है: मॉडल अनुभाग में, मैं Petमॉडल को कई बार देखता हूं । इन मॉडलों की सामग्री ठीक है। केवल नाम गलत हैं।
schellingerht

@schellingerht में editor2.swagger.ioआपको यह समस्या दिखाई नहीं देगी
Shiplu Mokaddim

एकमात्र मुद्दा जो मुझे विरासत को परिभाषित करने के इस तरीके से मिला है, वह यह है कि उत्पन्न वर्ग में पेटीएम प्रॉपर्टी थोड़ी बेकार है। यह खाली हो जाएगा। लेकिन कम से कम यह वर्ग पदानुक्रम उत्पन्न करता है जैसा मैंने सोचा था कि यह होगा। धन्यवाद!
xarlymg89

ऊपर के रूप में वंशानुक्रम जोंस बनाने के लिए, आपको अपने माता-पिता और बच्चों की कक्षाओं को निम्नानुसार एनोटेट करना होगा: @ApiModel (भेदभावकर्ता = "प्रकार", उपटिप्स = {Cat.class, Dog.class}) सार्वजनिक सार वर्ग {} @ @ ApiModel (माता-पिता = Animal.class) सार्वजनिक calss बिल्ली का विस्तार जानवर {}
जेनेट

क्या विभेदक का उपयोग केवल तब किया जाता है जब हम एक इंटरफ़ेस लागू करते हैं Pet, कैसे के बारे में अगर क्लास ए कक्षा बी का विस्तार करता है, तो क्या हमें भी इसका उपयोग करना चाहिए? धन्यवाद
Bionix1441

23

मैंने पाया है कि परिभाषा के बिना भी रचना ठीक काम करती है discriminator

उदाहरण के लिए, आधार Response:

definitions:
  Response:
    description: Default API response
    properties:
      status:
        description: Response status `success` or `error`
        type: string
        enum: ["success", "error"]
      error_details:
        description: Exception message if called
        type: ["string", "object", "null"]
      error_message:
        description: Human readable error message
        type: ["string", "null"]
      result:
        description: Result body
        type: ["object", "null"]
      timestamp:
        description: UTC timestamp in ISO 8601 format
        type: string
    required:
      - status
      - timestamp
      - error_details
      - error_message
      - result

के रूप में प्रस्तुत किया गया है:

प्रतिक्रिया दृश्य

और हम इसे resultक्षेत्र के कस्टम स्कीमा को परिष्कृत करने के लिए बढ़ा सकते हैं :

  FooServiceResponse:
    description: Response for Foo service
    allOf:
      - $ref: '#/definitions/Response'
      - properties:
          result:
            type: object
            properties:
              foo_field:
                type: integer
                format: int32
              bar_field:
                type: string
        required:
          - result

और इसे सही तरीके से प्रस्तुत किया जाएगा:

FooServiceResponse विज़ुअलाइज़ेशन

ध्यान दें, allOfयह काम करने के लिए पर्याप्त है और किसी भी discriminatorक्षेत्र का उपयोग नहीं किया जाता है। यह अच्छा है, क्योंकि यह काम करता है और यह महत्वपूर्ण है, जैसा कि मुझे लगता है, उपकरण बिना discriminatorफ़ील्ड के कोड उत्पन्न करने में सक्षम होंगे ।


मैंने भी इस्तेमाल किया है allOf, लेकिन किसी भी तरह openapi.yaml, मुझे लगता है कि उपवर्गों में अतिरेक में सुपर क्लास के गुण होते हैं, क्या यह सही है?
Bionix1441 16

9

यहां सभी उत्तर पहले से ही उत्कृष्ट हैं, लेकिन मैं सिर्फ रचना बनाम विरासत के बारे में एक मामूली नोट जोड़ना चाहता हूंSwagger / OpenAPI कल्पना के अनुसार , संरचना को लागू करने के लिए , allOfसंपत्ति का उपयोग करना पर्याप्त है, क्योंकि @oblalex सही ढंग से इंगित करता है । हालांकि, लागू करने के लिए विरासत , आप उपयोग करने की आवश्यकता allOfके साथ discriminatorके रूप में, द्वारा @ TomaszSętkowski उदाहरण

इसके अलावा, मुझे एपीआई अप्रेंटिस में रचना और विरासत दोनों के कुछ और स्वैगर उदाहरण मिले । वे Arnaud Lauret द्वारा एक उत्कृष्ट स्वैगर / OpenAPI ट्यूटोरियल श्रृंखला का हिस्सा हैं जो मुझे लगता है कि हर किसी को जांच करनी चाहिए।


1
@ प्रासंगिक लिंक पोस्ट करना एक अच्छी शुरुआत है, वास्तव में एक उपयोगी उत्तर होना चाहिए, आपको उस प्रासंगिक पाठ का भी हवाला देना चाहिए जो लिंक पर मिलेगा। लिंक-केवल उत्तर हतोत्साहित किए जाते हैं, क्योंकि लिंक अक्सर मृत हो जाएंगे।
स्टिजन डे विट

3

स्वैगर 2.0 मानक उदाहरण जो आपने साझा किया है, एक रचना संबंध को दर्शाता है, विशेष रूप से यह "एक प्रकार का" सुपर-प्रकार / उप-प्रकार का संबंध है, हालांकि यह स्वयं में और इसमें बहुरूपता नहीं है।

यह तब होगा जब आप इनपुट पैरामीटर के रूप में पेट की आधार परिभाषा को संदर्भित कर सकते हैं, फिर कैट को चुन सकते हैं या इनपुट अनुरोध के मूल्य के रूप में कैट जेएसएन ऑब्जेक्ट दर्ज कर सकते हैं, और स्वैगर यूआई के लिए यह स्वीकार्य है।

मुझे यह सीधे काम करने के लिए नहीं मिला।

सबसे अच्छा मैं जो काम कर सकता था वह बेस ऑब्जेक्ट (जैसे पेट) पर अतिरिक्त रूप से सही सेट करने के लिए था, पालतू को इनपुट स्कीमा के रूप में JSON पॉइंटर संदर्भ का उपयोग करके निर्दिष्ट करें, और अंत में स्वैगर यूआई में मेरे कैट जेएसएन वैल्यू ऑब्जेक्ट को कॉपी और पेस्ट करें। चूंकि अतिरिक्त गुणों की अनुमति है, इसलिए Swagger UI ने एक वैध इनपुट अनुरोध पेलोड उत्पन्न किया।


आप तार पर बहुरूपता नहीं करते हैं (या अपनी डेटा संस्थाओं को उजागर करते हैं) .. लेकिन जब तक आप इसे काम करने के लिए विशिष्ट हैक करने के लिए कसकर जोड़े नहीं चाहते हैं।
user1496062

बहुरूपता विरासत द्वारा सक्षम है, लेकिन विरासत का उपयोग करने के लिए आवश्यक नहीं है। तार्किक रूप से, वंशानुक्रम "ए-ए" संबंध है जबकि रचना "ए-ए" संबंध है। कार्यान्वयन भाषा और डोमेन उपयोग मामलों के आधार पर दोनों के बीच की रेखा धुंधली हो सकती है। लेकिन वह शुरुआती बिंदु है। Fwiw, विभेदक बहुरूपता प्रकारों के deserialization सक्षम बनाता है। अन्य दृष्टिकोण हैं (उदाहरण के लिए जावा वर्ग के नाम भी शामिल हैं)। लेकिन, सहमत हुए, ये मज़ेदार हो सकते हैं, पोर्टेबल नहीं। उदाहरण के लिए एक अजगर ग्राहक जावा वर्ग के नाम के साथ क्या करेगा?
चार्ली रिट्जेल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.