fix: support json serialization for parameter examples

fixes #934
This commit is contained in:
Roman Hotsiy 2019-08-01 11:17:50 +03:00
parent 2afc2e4921
commit 1367380a88
No known key found for this signature in database
GPG Key ID: 5CB7B3ACABA57CB0
4 changed files with 94 additions and 10 deletions

View File

@ -33,11 +33,10 @@ export class FieldDetails extends React.PureComponent<FieldProps> {
let exampleField: JSX.Element | null = null; let exampleField: JSX.Element | null = null;
if (showExamples) { if (showExamples && example !== undefined) {
const label = l('example') + ':'; const label = l('example') + ':';
if (field.in && field.style) { if (field.in && (field.style || field.serializationMime)) {
const serializedValue = const serializedValue = serializeParameterValue(field, example);
example !== undefined ? serializeParameterValue(field, example) : undefined;
exampleField = <FieldDetail label={label} value={serializedValue} raw={true} />; exampleField = <FieldDetail label={label} value={serializedValue} raw={true} />;
} else { } else {
exampleField = <FieldDetail label={label} value={example} />; exampleField = <FieldDetail label={label} value={example} />;

View File

@ -44,6 +44,8 @@ export class FieldModel {
explode: boolean; explode: boolean;
style?: OpenAPIParameterStyle; style?: OpenAPIParameterStyle;
serializationMime?: string;
constructor( constructor(
parser: OpenAPIParser, parser: OpenAPIParser,
infoOrRef: Referenced<OpenAPIParameter> & { name?: string; kind?: string }, infoOrRef: Referenced<OpenAPIParameter> & { name?: string; kind?: string },
@ -55,12 +57,22 @@ export class FieldModel {
this.name = infoOrRef.name || info.name; this.name = infoOrRef.name || info.name;
this.in = info.in; this.in = info.in;
this.required = !!info.required; this.required = !!info.required;
this.schema = new SchemaModel(parser, info.schema || {}, pointer, options);
let fieldSchema = info.schema;
let serializationMime = '';
if (!fieldSchema && info.in && info.content) {
serializationMime = Object.keys(info.content)[0];
fieldSchema = info.content[serializationMime] && info.content[serializationMime].schema;
}
this.schema = new SchemaModel(parser, fieldSchema || {}, pointer, options);
this.description = this.description =
info.description === undefined ? this.schema.description || '' : info.description; info.description === undefined ? this.schema.description || '' : info.description;
this.example = info.example || this.schema.example; this.example = info.example || this.schema.example;
if (info.style) { if (serializationMime) {
this.serializationMime = serializationMime;
} else if (info.style) {
this.style = info.style; this.style = info.style;
} else if (this.in) { } else if (this.in) {
this.style = getDefaultStyleValue(this.in); this.style = getDefaultStyleValue(this.in);

View File

@ -11,7 +11,7 @@ import {
serializeParameterValue, serializeParameterValue,
} from '../'; } from '../';
import { OpenAPIParser } from '../../services'; import { FieldModel, OpenAPIParser, RedocNormalizedOptions } from '../../services';
import { OpenAPIParameter, OpenAPIParameterLocation, OpenAPIParameterStyle } from '../../types'; import { OpenAPIParameter, OpenAPIParameterLocation, OpenAPIParameterStyle } from '../../types';
import { expandDefaultServerVariables } from '../openapi'; import { expandDefaultServerVariables } from '../openapi';
@ -389,6 +389,7 @@ describe('Utils', () => {
explode: boolean; explode: boolean;
expected: string; expected: string;
} }
interface TestValueTypeGroup { interface TestValueTypeGroup {
value: any; value: any;
description: string; description: string;
@ -565,5 +566,51 @@ describe('Utils', () => {
}); });
}); });
}); });
describe('advanced serialization', () => {
it('should serialize correctly query parameter with content with application/json', () => {
const parameter: OpenAPIParameter = {
name: 'id',
in: 'query',
content: {
'application/json': {
schema: {
type: 'string',
},
},
},
};
const parser = new OpenAPIParser({ openapi: '3.0' } as any);
const opts = new RedocNormalizedOptions({});
const field = new FieldModel(parser, parameter, '', opts);
expect(serializeParameterValue(field, { name: 'test', age: 23 })).toEqual(
'id={"name":"test","age":23}',
);
});
it('should serialize correctly header parameter with content with application/json', () => {
const parameter: OpenAPIParameter = {
name: 'x-header',
in: 'header',
content: {
'application/json': {
schema: {
type: 'string',
},
},
},
};
const parser = new OpenAPIParser({ openapi: '3.0' } as any);
const opts = new RedocNormalizedOptions({});
const field = new FieldModel(parser, parameter, '', opts);
expect(serializeParameterValue(field, { name: 'test', age: 23 })).toEqual(
'{"name":"test","age":23}',
);
});
});
}); });
}); });

View File

@ -308,11 +308,37 @@ function serializeCookieParameter(
} }
} }
export function serializeParameterValue(parameter: OpenAPIParameter, value: any): string { export function serializeParameterValueWithMime(value: any, mime: string): string {
const { name, style, explode = false } = parameter; if (isJsonLike(mime)) {
return JSON.stringify(value);
} else {
console.warn(`Parameter serialization as ${mime} is not supported`);
return '';
}
}
export function serializeParameterValue(
parameter: OpenAPIParameter & { serializationMime?: string },
value: any,
): string {
const { name, style, explode = false, serializationMime } = parameter;
if (serializationMime) {
switch (parameter.in) {
case 'path':
case 'header':
return serializeParameterValueWithMime(value, serializationMime);
case 'cookie':
case 'query':
return `${name}=${serializeParameterValueWithMime(value, serializationMime)}`;
default:
console.warn('Unexpected parameter location: ' + parameter.in);
return '';
}
}
if (!style) { if (!style) {
console.warn(`Missing style attribute for parameter ${name}`); console.warn(`Missing style attribute or content for parameter ${name}`);
return ''; return '';
} }