_From @JacquesPerrault on March 5, 2016 17:39_
When the following is placed into the Swagger editor, the ui will show either the PUT or the PATCH, but not both. Additionally, if the editor is shut down, then restarted, it crashes, requiring a manual edit of the swagger.yaml in order to get the editor going again. Swagger definition and stack track posted below.
swagger definition
/widget/{widgetId}:
x-swagger-router-controller: widgetPut
put:
summary: Update a widget
operationId: widgetPut
consumes: ["application/json"]
produces: ["application/json"]
parameters:
- name: widgetId
in: path
description: The UID of the widget
required: true
type: string
- name: body
in: body
description: widget content
required: true
schema:
type: object
responses:
"200":
description: OK
schema:
$ref: "#/definitions/SuccessResponse"
default:
description: Error
schema:
$ref: "#/definitions/ErrorResponse"
/widget/{widgetId}:
x-swagger-router-controller: widgetPatch
patch:
summary: Patch a widget
operationId: widgetPatch
consumes: ["application/json"]
produces: ["application/json"]
parameters:
- name: widgetId
in: path
description: The UID of the widget
required: true
type: string
- name: body
in: body
description: widget content
required: true
schema:
type: object
responses:
"200":
description: OK
schema:
$ref: "#/definitions/SuccessResponse"
default:
description: Error
schema:
$ref: "#/definitions/ErrorResponse"
* stack trace **
_line 113_ is referring to the second instance of the mapping key, which in this case is the patch version.
{ [YAMLException: duplicated mapping key at line 113, column 3:
/messages/{messageId}:
^]
name: 'YAMLException',
reason: 'duplicated mapping key',
mark:
Mark {
name: null,
buffer: 'swagger: "2.0"\r\ninfo:\r\n version: "0.0.1"\r\n title: Project Castle APIs\r\n# during dev, should point to your local machine\r\nhost: localhost:10010\r\n# basePath prefixes all resource paths \r\nbasePath: /\r\n# \r\nschemes:\r\n # tip: remove http to make production-grade\r\n - http\r\n - https\r\n# format of bodies a client can send (Content-Type)\r\nconsumes:\r\n - applic
ation/json\r\n# format of the responses to the client (Accepts)\r\nproduces:\r\n - application/json\r\npaths:\r\n\r\n /messages:\r\n x-swagger-router-controller: messagesCreateOrSend\r\n post:\r\n summary: Create and/or send a message\r\n description: The message entity is entirely defined by the object passed in `body`, and is intentionally left implementation agnostic. If `sen
d` is *false* the message should be saved as a draft, otherwise the message should be marked for delivery. Either way, return the resulting `messageId`. This endpoint MUST be called to create a message; updates should use **PUT /messages/{messageId}** or **PATCH /messages/{messageId}** \r\n operationId: messagesCreateOrSend\r\n consumes: ["application/json"]\r\n produces: ["applic
ation/json"]\r\n parameters:\r\n - name: send\r\n in: query\r\n description: send message if *true*, save as draft otherwise\r\n required: true\r\n type: boolean\r\n - name: body\r\n in: body\r\n description: message content\r\n required: true\r\n schema:\r\n type: object\r\n responses:\r\n
"200":\r\n description: OK\r\n schema:\r\n $ref: "#/definitions/ObjectResponse"\r\n default:\r\n description: Error\r\n schema:\r\n $ref: "#/definitions/ErrorResponse"\r\n\r\n\r\n /widget/{widgetId}:\r\n x-swagger-router-controller: widgetPut\r\n put:\r\n summary: Update a widget\r\n operationId: widgetPut\r\n
consumes: ["application/json"]\r\n produces: ["application/json"]\r\n parameters:\r\n - name: widgetId\r\n in: path\r\n description: The UID of the widget\r\n required: true\r\n type: string\r\n - name: body\r\n in: body\r\n description: widget content\r\n required: true\r\n schema:\r\n
type: object\r\n responses:\r\n "200":\r\n description: OK\r\n schema:\r\n $ref: "#/definitions/ObjectResponse"\r\n default:\r\n description: Error\r\n schema:\r\n $ref: "#/definitions/ErrorResponse"\r\n\r\n\r\n /widget/{widgetId}:\r\n x-swagger-router-controller: widgetPatch\r\n patch:\r\n summary: Patch a wi
dget\r\n operationId: widgetPatch\r\n consumes: ["application/json"]\r\n produces: ["application/json"]\r\n parameters:\r\n - name: widgetId\r\n in: path\r\n description: The UID of the widget\r\n required: true\r\n type: string\r\n - name: body\r\n in: body\r\n description: widget content\r\n required
: true\r\n schema:\r\n type: object\r\n responses:\r\n "200":\r\n description: OK\r\n schema:\r\n $ref: "#/definitions/ObjectResponse"\r\n default:\r\n description: Error\r\n schema:\r\n $ref: "#/definitions/ErrorResponse"\r\n\r\n\r\n /messages/{messageId}:\r\n x-swagger-router-controller: messages
UpdateOrSend\r\n put:\r\n summary: Update or send a message\r\n description: If `send` is *false* update the message, otherwise send the message. Either way, return the messageId.\r\n operationId: messagesUpdateOrSend\r\n consumes: ["application/json"]\r\n produces: ["application/json"]\r\n parameters:\r\n - name: messageId\r\n in: path\r\n
description: The UID of the message\r\n required: true\r\n type: string\r\n - name: send\r\n in: query\r\n description: send message if *true*, save as draft otherwise\r\n required: true\r\n type: boolean\r\n - name: body\r\n in: body\r\n description: message content\r\n required: true\r\n sch
ema:\r\n type: object\r\n responses:\r\n "200":\r\n description: OK\r\n schema:\r\n $ref: "#/definitions/ObjectResponse"\r\n default:\r\n description: Error\r\n schema:\r\n $ref: "#/definitions/ErrorResponse"\r\n\r\n\r\n /attachments/{messageId}:\r\n x-swagger-router-controller: attachments\r\n post:\r\n
summary: Attach a file residing on the user\'s device to a message\r\n description: This endpoint should return the URI of the attachment\r\n operationId: attachments\r\n consumes: ["application/json"]\r\n produces: ["application/json"]\r\n parameters:\r\n - name: messageId\r\n in: path\r\n description: The UID of the message to be associated
with the attachment\r\n required: true\r\n type: string\r\n - name: body\r\n in: body\r\n description: encoded attchment content\r\n required: true\r\n schema:\r\n type: object\r\n responses:\r\n "200":\r\n description: OK\r\n schema:\r\n $ref: "#/definitions/ObjectResponse"\r\n
default:\r\n description: Error\r\n schema:\r\n $ref: "#/definitions/ErrorResponse"\r\n\r\n\r\n /search/messages:\r\n x-swagger-router-controller: searchMessages\r\n post:\r\n summary: Returns messages for the authenticated user\r\n description: Messages can be filtered using predefined parameters, or arbitrary search parameters can be defined using t
he \'arbitraryFilterParams\' parameter.\r\n operationId: searchMessages\r\n consumes: ["application/json"]\r\n produces: ["application/json"]\r\n parameters:\r\n - name: body\r\n in: body\r\n description: Filters to use as part of the search\r\n required: true\r\n schema:\r\n $ref: "#/definitions/Filter"\r\n responses:\
r\n "200":\r\n description: OK\r\n schema:\r\n $ref: "#/definitions/ObjectResponse"\r\n default:\r\n description: Error\r\n schema:\r\n $ref: "#/definitions/ErrorResponse"\r\n\r\n\r\n# complex objects have schema definitions\r\ndefinitions:\r\n\r\n Filter:\r\n type: object\r\n properties:\r\n limit:\r\n type
: string\r\n description: Number of messages to return. Limit is applied after messages have been filtered and sorted.\r\n tags:\r\n type: array\r\n description: List of tags to filter on. Only messages associated with these tags will be returned.\r\n items:\r\n type: string\r\n userId:\r\n type: string\r\n description: Only messages b
elonging to the specified userId will be returned. This can be used for delegation; the auth token pasesed with the request will be used to determine entitlement.\r\n sortOrder:\r\n type: array\r\n description: An arbitrary string passed to the adapter ("ascending", "descending", "sentiment", etc). Implementation is adapter-specific. Should only be applied after all filtering
is complete.\r\n items:\r\n type: string\r\n startDate:\r\n type: string\r\n description: Only messages created/sent/received on or after this date will be returned. Will work in conjunction with "endDate".\r\n endDate:\r\n type: string\r\n description: Only messages created/sent/received on or before this date will be returned. Will work in
conjunction with "endDate".\r\n sentiment:\r\n type: array\r\n description: The sentiment of the message. Can be one or more values between 1.0 and -1.0\r\n items:\r\n type: number\r\n arbitraryFilterParams:\r\n type: object\r\n description: Used to pass arbitrary key/value parameters to the adapter\r\n\r\n\r\n ObjectResponse:\r\n type: s
tring\r\n description: Used to return an arbitrary string and an array of objects, both optional.\r\n properties:\r\n message:\r\n type: string\r\n data:\r\n type: array\r\n items:\r\n type: object\r\n\r\n\r\n ErrorResponse:\r\n required:\r\n - message\r\n properties:\r\n message:\r\n type: string\r\n\u0000',
position: 3295,
line: 112,
column: 2 },
message: 'duplicated mapping key at line 113, column 3:\n /messages/{messageId}:\n ^' }
_Copied from original issue: swagger-api/swagger-core#1700_
Put them both under the same path and it will work. JSON doesn't allow duplicate keys.
Thanks for the feedback, that worked nicely!
@webron I thought it worked, but while put/patch/delete all appear in the edit ui, I get the same error when I restart the editor. My definition is below, is there a different way I should be defining different methods (e.g. put/patch/delete) for the same path?
/messages/{messageId}:
x-swagger-router-controller: messagesUpdateOrSend
put:
summary: Update/send a message
description: The `PUT` method should be used where it is desireable to submitting every property whether it changed or not (as opposed to updating discrete properties of a message). This endpoint MUST NOT be called if a `messageId` is not available. If `send=false` the message MUST be saved as a draft, otherwise the message MUST be marked for delivery.
operationId: messagesUpdateOrSend
consumes: ["application/json"]
produces: ["application/json"]
parameters:
- name: messageId
in: path
description: A UID used by the proxy to uniquely identify the message.
required: true
type: string
- name: send
in: query
description: Send message if `query=true`, save as draft if `query=false`
required: true
type: boolean
- name: token
in: query
description: auth token, if not included in header. Example `token=[Token]`
required: false
type: string
- name: body
in: body
description: This object must contain some (or all) message properties for a particular back end application server (e.g. Domino, Exchange, Gmail, Yahoo). Example `body {"to":"joesmith%40email.com","from":"janesmith%40email.com","subject":"This is a test","body":"Can you hear me now%3F","tags":["keepers","follow up"],"flags":["urgent","confidential"],...}`
required: true
schema:
type: object
responses:
"200":
description: Success/OK
schema:
$ref: "#/definitions/SuccessResponse"
default:
description: Error
schema:
$ref: "#/definitions/ErrorResponse"
x-swagger-router-controller: messagesPatchOrSend
patch:
summary: Update/send a message
description: The `PATCH` method should be used where it is desireable to change discrete properties of a message (as opposed to updating every property whether it changed or not). This endpoint can only be called if a `messageId` is available. If `send=false` update the message, otherwise mark the message for delivery.
operationId: messagesPatchOrSend
consumes: ["application/json"]
produces: ["application/json"]
parameters:
- name: messageId
in: path
description: A UID used by the proxy to uniquely identify the message.
required: true
type: string
- name: send
in: query
description: Send message if `query=true`, save as draft if `query=false`
required: true
type: boolean
- name: token
in: query
description: auth token, if not included in header. Example `token=[Token]`
required: false
type: string
- name: body
in: body
description: This object should only contain fields to be updated. Example `body {"subject":"This is another test","body":"Is there anybody out there%3F",...}`
required: true
schema:
type: object
responses:
"200":
description: Success/OK
schema:
$ref: "#/definitions/SuccessResponse"
default:
description: Error
schema:
$ref: "#/definitions/ErrorResponse"
x-swagger-router-controller: messagesDelete
delete:
summary: Delete a single message
description: Delete the message associated with `messageId` and all associated attachments. Attachments can be resolved by the proxy server using `messageId` and need not be included in the request payload.
operationId: messagesDelete
consumes: ["application/json"]
produces: ["application/json"]
parameters:
- name: messageId
in: path
description: UID of the message to be deleted
required: true
type: string
- name: token
in: query
description: auth token, if not included in header. Example `token=[Token]`
required: false
type: string
responses:
"200":
description: Success/OK.
schema:
$ref: "#/definitions/SuccessResponse"
default:
description: Error
schema:
$ref: "#/definitions/ErrorResponse"
What error are you getting? Seems to load fine for me.
@JacquesPerrault - same as the original issue. You have x-swagger-router-controller twice under the same level, which is not allowed.
@webron ah, so you'd only have one controller for all three methods?
Sounds like, yeah.
@webron thanks. I removed the x-swagger-router-controller entirely and left the operationId. Seems happy now.
Thanks for the update, glad it worked out.
Most helpful comment
Put them both under the same path and it will work. JSON doesn't allow duplicate keys.