2019-09-25 14:54:02 +02:00
|
|
|
{******************************************************************************}
|
|
|
|
{ }
|
|
|
|
{ Delphi SwagDoc Library }
|
|
|
|
{ Copyright (c) 2018 Marcelo Jaloto }
|
|
|
|
{ https://github.com/marcelojaloto/SwagDoc }
|
|
|
|
{ }
|
|
|
|
{******************************************************************************}
|
|
|
|
{ }
|
|
|
|
{ Licensed under the Apache License, Version 2.0 (the "License"); }
|
|
|
|
{ you may not use this file except in compliance with the License. }
|
|
|
|
{ You may obtain a copy of the License at }
|
|
|
|
{ }
|
|
|
|
{ http://www.apache.org/licenses/LICENSE-2.0 }
|
|
|
|
{ }
|
|
|
|
{ Unless required by applicable law or agreed to in writing, software }
|
|
|
|
{ distributed under the License is distributed on an "AS IS" BASIS, }
|
|
|
|
{ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. }
|
|
|
|
{ See the License for the specific language governing permissions and }
|
|
|
|
{ limitations under the License. }
|
|
|
|
{ }
|
|
|
|
{******************************************************************************}
|
|
|
|
|
|
|
|
unit Swag.Doc.Path.Operation.RequestParameter;
|
|
|
|
|
|
|
|
interface
|
|
|
|
|
|
|
|
uses
|
2019-10-24 15:34:40 +02:00
|
|
|
System.SysUtils,
|
|
|
|
System.Classes,
|
|
|
|
System.Generics.Collections,
|
2019-09-25 14:54:02 +02:00
|
|
|
System.JSON,
|
|
|
|
Swag.Common.Types,
|
|
|
|
Swag.Doc.Definition;
|
|
|
|
|
|
|
|
type
|
|
|
|
/// <summary>
|
|
|
|
/// Describes a single operation parameter.
|
|
|
|
/// A unique parameter is defined by a combination of a name and location.
|
|
|
|
/// </summary>
|
|
|
|
TSwagRequestParameter = class(TObject)
|
|
|
|
private
|
|
|
|
fName: string;
|
|
|
|
fInLocation: TSwagRequestParameterInLocation;
|
|
|
|
fRequired: Boolean;
|
|
|
|
fSchema: TSwagDefinition;
|
|
|
|
fDescription: string;
|
|
|
|
fTypeParameter: TSwagTypeParameter;
|
|
|
|
fPattern: string;
|
|
|
|
fItems: TJSONObject;
|
|
|
|
fFormat: string;
|
2019-10-24 15:34:40 +02:00
|
|
|
fDefault: string;
|
|
|
|
fEnum: TStringList;
|
|
|
|
fAllowEmptyValue: Boolean;
|
|
|
|
fRef: string;
|
|
|
|
procedure SetAllowEmptyValue(const pValue: Boolean);
|
2019-09-25 14:54:02 +02:00
|
|
|
protected
|
|
|
|
function ReturnInLocationToString: string;
|
|
|
|
public
|
|
|
|
constructor Create; reintroduce;
|
|
|
|
destructor Destroy; override;
|
|
|
|
|
|
|
|
function GenerateJsonObject: TJSONObject;
|
|
|
|
procedure Load(pJson: TJSONObject);
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// There are five possible parameter types: Query, Header, Path, Form e Body.
|
|
|
|
/// </summary>
|
|
|
|
property InLocation: TSwagRequestParameterInLocation read fInLocation write fInLocation;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Required. The name of the parameter. Parameter names are case sensitive.
|
|
|
|
/// If in is "path", the name field MUST correspond to the associated path segment from the path field in the Paths Object.
|
|
|
|
/// See Path Templating for further information.
|
|
|
|
/// For all other cases, the name corresponds to the parameter name used based on the in property.
|
|
|
|
/// </summary>
|
|
|
|
property Name: string read fName write fName;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// A brief description of the parameter. This could contain examples of use. GFM syntax can be used for rich text representation.
|
|
|
|
/// </summary>
|
|
|
|
property Description: string read fDescription write fDescription;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Determines whether this parameter is mandatory. If the parameter is in "path", this property is required and its value MUST be true.
|
|
|
|
/// Otherwise, the property MAY be included and its default value is false.
|
|
|
|
/// </summary>
|
|
|
|
property Required: Boolean read fRequired write fRequired;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.2.3.
|
|
|
|
/// </summary>
|
|
|
|
property Pattern: string read fPattern write fPattern;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// If in is "body"
|
|
|
|
/// Required. The schema defining the type used for the body parameter.
|
|
|
|
/// </summary>
|
|
|
|
property Schema: TSwagDefinition read fSchema;
|
|
|
|
|
|
|
|
property Items: TJSONObject read fItems;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// If in is any value other than "body"
|
|
|
|
/// Required. The type of the parameter. Since the parameter is not located at the request body, it is limited to
|
|
|
|
/// simple types (that is, not an object).
|
|
|
|
/// The value MUST be one of "string", "number", "integer", "boolean", "array" or "file".
|
|
|
|
/// If type is "file", the consumes MUST be either "multipart/form-data", " application/x-www-form-urlencoded" or both
|
|
|
|
/// and the parameter MUST be in "formData".
|
|
|
|
/// </summary>
|
|
|
|
property TypeParameter: TSwagTypeParameter read fTypeParameter write fTypeParameter;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Primitives have an optional modifier property format. Swagger uses several known formats to more finely define
|
|
|
|
/// the data type being used. However, the format property is an open string-valued property, and can have any value
|
|
|
|
/// to support documentation needs. Formats such as "email", "uuid", etc., can be used even though they are not
|
|
|
|
/// defined by this specification.
|
|
|
|
/// </summary>
|
|
|
|
property Format: string read fFormat write fFormat;
|
|
|
|
|
2019-10-24 15:34:40 +02:00
|
|
|
/// <summary>
|
|
|
|
/// Declares the value of the parameter that the server will use if none is provided, for example a "count" to
|
|
|
|
/// control the number of results per page might default to 100 if not supplied by the client in the request.
|
|
|
|
/// (Note: "default" has no meaning for required parameters.)
|
|
|
|
/// See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-6.2. Unlike JSON Schema
|
|
|
|
/// this value MUST conform to the defined type for this parameter.
|
|
|
|
property Default: string read fDefault write fDefault;
|
|
|
|
|
|
|
|
|
|
|
|
property Enum: TStringList read fEnum;
|
|
|
|
|
|
|
|
property AllowEmptyValue: Boolean read fAllowEmptyValue write SetAllowEmptyValue;
|
|
|
|
|
|
|
|
property Ref: string read fRef write fRef;
|
2019-09-25 14:54:02 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
implementation
|
|
|
|
|
|
|
|
uses
|
|
|
|
System.StrUtils,
|
|
|
|
Swag.Common.Consts,
|
|
|
|
Swag.Common.Types.Helpers;
|
|
|
|
|
|
|
|
const
|
|
|
|
c_SwagRequestParameterIn = 'in';
|
|
|
|
c_SwagRequestParameterName = 'name';
|
|
|
|
c_SwagRequestParameterDescription = 'description';
|
|
|
|
c_SwagRequestParameterRequired = 'required';
|
|
|
|
c_SwagRequestParameterSchema = 'schema';
|
|
|
|
c_SwagRequestParameterType = 'type';
|
2019-10-24 15:34:40 +02:00
|
|
|
c_SwagRequestParameterDefault = 'default';
|
2019-09-25 14:54:02 +02:00
|
|
|
c_SwagRequestParameterPattern = 'pattern';
|
|
|
|
c_SwagRequestParameterFormat = 'format';
|
2019-10-24 15:34:40 +02:00
|
|
|
c_SwagRequestParameterEnum = 'enum';
|
|
|
|
c_SwagRequestParameterAllowEmptyValue = 'allowEmptyValue';
|
|
|
|
c_SwagRequestParameterRef = '$ref';
|
2019-09-25 14:54:02 +02:00
|
|
|
|
|
|
|
{ TSwagRequestParameter }
|
|
|
|
|
|
|
|
constructor TSwagRequestParameter.Create;
|
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
fSchema := TSwagDefinition.Create;
|
2019-10-24 15:34:40 +02:00
|
|
|
fEnum := TStringList.Create;
|
2019-09-25 14:54:02 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
destructor TSwagRequestParameter.Destroy;
|
|
|
|
begin
|
|
|
|
FreeAndNil(fSchema);
|
2019-10-24 15:34:40 +02:00
|
|
|
FreeAndNil(fEnum);
|
2019-09-25 14:54:02 +02:00
|
|
|
inherited Destroy;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TSwagRequestParameter.GenerateJsonObject: TJSONObject;
|
|
|
|
var
|
|
|
|
vJsonObject: TJsonObject;
|
2019-10-24 15:34:40 +02:00
|
|
|
vJsonEnum: TJSONArray;
|
|
|
|
vIndex: Integer;
|
2019-09-25 14:54:02 +02:00
|
|
|
begin
|
|
|
|
vJsonObject := TJsonObject.Create;
|
2019-10-24 15:34:40 +02:00
|
|
|
|
|
|
|
if fRef.Length > 0 then
|
|
|
|
begin
|
|
|
|
vJsonObject.AddPair('$ref', fRef);
|
|
|
|
Result := vJsonObject;
|
|
|
|
Exit;
|
|
|
|
end;
|
|
|
|
|
2019-09-25 14:54:02 +02:00
|
|
|
vJsonObject.AddPair(c_SwagRequestParameterIn, ReturnInLocationToString);
|
|
|
|
vJsonObject.AddPair(c_SwagRequestParameterName, fName);
|
|
|
|
if not fDescription.IsEmpty then
|
|
|
|
vJsonObject.AddPair(c_SwagRequestParameterDescription, fDescription);
|
|
|
|
if not fPattern.IsEmpty then
|
|
|
|
vJsonObject.AddPair(c_SwagRequestParameterPattern, fPattern);
|
2019-10-24 15:34:40 +02:00
|
|
|
if not fDefault.IsEmpty then
|
|
|
|
vJsonObject.AddPair(c_SwagRequestParameterDefault, fDefault);
|
2019-09-25 14:54:02 +02:00
|
|
|
|
2019-10-24 15:34:40 +02:00
|
|
|
if fRequired or (fInLocation = rpiPath) then
|
|
|
|
vJsonObject.AddPair(c_SwagRequestParameterRequired, TJSONBool.Create(True));
|
2019-09-25 14:54:02 +02:00
|
|
|
|
2019-10-24 15:34:40 +02:00
|
|
|
if fAllowEmptyValue and (fInLocation = rpiQuery) or (fInLocation = rpiFormData) then
|
|
|
|
vJsonObject.AddPair(c_SwagRequestParameterAllowEmptyValue, TJSONBool.Create(True));
|
2019-09-25 14:54:02 +02:00
|
|
|
|
2019-10-24 15:34:40 +02:00
|
|
|
if fInLocation = rpiBody then // schema only allow in body parameters
|
|
|
|
begin
|
|
|
|
if (not fSchema.Name.IsEmpty) then
|
|
|
|
vJsonObject.AddPair(c_SwagRequestParameterSchema, fSchema.GenerateJsonRefDefinition)
|
|
|
|
else if Assigned(fSchema.JsonSchema) then
|
2020-05-21 00:43:30 +02:00
|
|
|
vJsonObject.AddPair(c_SwagRequestParameterSchema, fSchema.JsonSchema.Clone as TJSONObject);
|
2019-10-24 15:34:40 +02:00
|
|
|
end;
|
|
|
|
if (fTypeParameter <> stpNotDefined) then
|
2019-09-25 14:54:02 +02:00
|
|
|
vJsonObject.AddPair(c_SwagRequestParameterType, c_SwagTypeParameter[fTypeParameter]);
|
|
|
|
|
|
|
|
if not fFormat.IsEmpty then
|
|
|
|
vJsonObject.AddPair(c_SwagRequestParameterFormat, fFormat);
|
|
|
|
|
2019-10-24 15:34:40 +02:00
|
|
|
if fEnum.Count > 0 then
|
|
|
|
begin
|
|
|
|
vJsonEnum := TJSONArray.Create;
|
|
|
|
for vIndex := 0 to fEnum.Count - 1 do
|
|
|
|
begin
|
|
|
|
vJsonEnum.Add(fEnum[vIndex]);
|
|
|
|
end;
|
|
|
|
vJsonObject.AddPair(c_SwagRequestParameterEnum, vJsonEnum);
|
|
|
|
end;
|
|
|
|
|
2019-09-25 14:54:02 +02:00
|
|
|
Result := vJsonObject;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TSwagRequestParameter.Load(pJson: TJSONObject);
|
2019-10-24 15:34:40 +02:00
|
|
|
var
|
|
|
|
vEnum: TJSONArray;
|
|
|
|
i: Integer;
|
2019-09-25 14:54:02 +02:00
|
|
|
begin
|
2019-10-24 15:34:40 +02:00
|
|
|
if Assigned(pJson.Values[c_SwagRequestParameterRef]) then
|
|
|
|
begin
|
|
|
|
fRef := pJson.Values[c_SwagRequestParameterRef].Value;
|
|
|
|
Exit;
|
|
|
|
end;
|
|
|
|
|
|
|
|
if Assigned(pJson.Values[c_SwagRequestParameterIn]) then
|
|
|
|
fInLocation.ToType(pJson.Values[c_SwagRequestParameterIn].Value);
|
|
|
|
|
|
|
|
if Assigned(pJson.Values[c_SwagRequestParameterAllowEmptyValue]) and
|
|
|
|
((fInLocation = rpiQuery) or (fInLocation = rpiFormData)) then
|
|
|
|
fAllowEmptyValue := (pJson.Values[c_SwagRequestParameterAllowEmptyValue] as TJSONBool).AsBoolean;
|
|
|
|
|
2019-09-25 14:54:02 +02:00
|
|
|
if Assigned(pJson.Values[c_SwagRequestParameterRequired]) then
|
|
|
|
fRequired := (pJson.Values[c_SwagRequestParameterRequired] as TJSONBool).AsBoolean
|
|
|
|
else
|
|
|
|
fRequired := False;
|
|
|
|
|
|
|
|
if Assigned(pJson.Values[c_SwagRequestParameterPattern]) then
|
|
|
|
fPattern := pJson.Values[c_SwagRequestParameterPattern].Value;
|
|
|
|
|
|
|
|
if Assigned(pJson.Values[c_SwagRequestParameterName]) then
|
|
|
|
fName := pJson.Values[c_SwagRequestParameterName].Value;
|
|
|
|
|
|
|
|
if Assigned(pJson.Values[c_SwagRequestParameterDescription]) then
|
|
|
|
fDescription := pJson.Values[c_SwagRequestParameterDescription].Value;
|
|
|
|
|
|
|
|
if Assigned(pJson.Values[c_SwagRequestParameterFormat]) then
|
|
|
|
fFormat := pJson.Values[c_SwagRequestParameterFormat].Value;
|
|
|
|
|
|
|
|
if Assigned(pJson.Values[c_SwagRequestParameterType]) then
|
|
|
|
fTypeParameter.ToType(pJson.Values[c_SwagRequestParameterType].Value);
|
|
|
|
|
2019-10-24 15:34:40 +02:00
|
|
|
if Assigned(pJson.Values[c_SwagRequestParameterDefault]) then
|
|
|
|
fDefault := pJson.Values[c_SwagRequestParameterDefault].Value;
|
|
|
|
|
2019-09-25 14:54:02 +02:00
|
|
|
if Assigned(pJson.Values[c_SwagRequestParameterSchema]) then
|
2019-10-24 15:34:40 +02:00
|
|
|
fSchema.JsonSchema := pJson.Values[c_SwagRequestParameterSchema].Clone as TJSONObject;
|
2019-09-25 14:54:02 +02:00
|
|
|
|
|
|
|
if Assigned(pJson.Values['items']) then
|
|
|
|
fItems := pJson.Values['items'] as TJSONObject;
|
|
|
|
|
2019-10-24 15:34:40 +02:00
|
|
|
if Assigned(pJson.Values[c_SwagRequestParameterEnum]) then
|
|
|
|
begin
|
|
|
|
vEnum := pJson.Values[c_SwagRequestParameterEnum] as TJSONArray;
|
|
|
|
for i := 0 to vEnum.Count - 1 do
|
|
|
|
begin
|
|
|
|
fEnum.Add(vEnum.Items[i].Value);
|
|
|
|
end;
|
|
|
|
end;
|
2019-09-25 14:54:02 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
function TSwagRequestParameter.ReturnInLocationToString: string;
|
|
|
|
begin
|
|
|
|
Result := c_SwagRequestParameterInLocation[fInLocation];
|
|
|
|
end;
|
|
|
|
|
2019-10-24 15:34:40 +02:00
|
|
|
procedure TSwagRequestParameter.SetAllowEmptyValue(const pValue: Boolean);
|
|
|
|
begin
|
|
|
|
if (fInLocation = rpiQuery) or (fInLocation = rpiFormData) then
|
|
|
|
fAllowEmptyValue := pValue
|
|
|
|
else
|
|
|
|
raise Exception.Create('allowEmptyValue not allowed to be set on ' + ReturnInLocationToString);
|
|
|
|
end;
|
|
|
|
|
2019-09-25 14:54:02 +02:00
|
|
|
end.
|