有没有办法在 Hapi Swagger 使用的 Joi 模型中将整数 属性 定义为 int64
Is there a way to define an integer property as int64 in a Joi model that is used by Hapi Swagger
我有以下 Joi
型号
const SimpleModel = Joi.object({
id: Joi.number().integer().required().description('ID')
}).label('SimpleModel');
该模型正在下面的 @hapi/hapi
路线中使用
{
method: 'GET',
path: `/api/v1.0/data`,
handler: () => { id: 1 }, // a mock handler
config: {
plugins: {
'hapi-swagger': {
responses: {
200: {
description: 'OK',
schema: SimpleModel
}
}
}
}
}
}
上面的模型生成如下面的 swagger 定义
swagger: '2.0'
host: localhost:8080
basePath: /api
info:
title: 'Swagger for SimpleModel'
version: '1.0'
schemes:
- http
- https
paths:
/v1.0/data:
get:
summary: Returns an object
responses:
'200':
schema:
$ref: '#/definitions/SimpleModel'
description: OK
definitions:
SimpleModel:
type: object
properties:
id:
type: integer
description: ID
required:
- id
我想要的是在id
中添加一个额外的字段,即format: int64
,例如
definitions:
SimpleModel:
type: object
properties:
id:
type: integer
format: int64 # <-- new field here!
description: ID
required:
- id
虽然这是由 swagger 支持的,但我找不到任何方法在我的 Joi
模型中定义它,以便它会出现在 hapi-swagger
生成的 swagger 中。
我在网上搜索了好几天,但在网上找不到任何有用的东西,无论是文档还是示例。
有没有办法在 SimpleModel
生成的 swagger 中包含 format: int64
?
package.json
{
"name": "71422008",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"@hapi/hapi": "^20.2.1",
"@hapi/inert": "^6.0.5",
"@hapi/vision": "^6.1.0",
"blipp": "^4.0.2",
"hapi-swagger": "^14.2.5",
"joi": "^17.6.0",
"qs": "^6.10.3"
}
}
index.js
const Hapi = require('@hapi/hapi');
const Joi = require('joi');
const Blipp = require('blipp');
const Inert = require('@hapi/inert');
const Vision = require('@hapi/vision');
const HapiSwagger = require('hapi-swagger');
const HapiSwaggerProperties = require('hapi-swagger/lib/properties');
const _parseNumber = HapiSwaggerProperties.prototype.parseNumber;
HapiSwaggerProperties.prototype.parseNumber = function(property, joiObj) {
let _property = _parseNumber.apply(this, [property, joiObj]);
_property.format = 'int64';
return _property;
}
const SimpleModel = Joi.object({
id: Joi.number().integer().required().description('ID')
}).label('SimpleModel');
const ser = async () => {
const swaggerOptions = {
info: {
title: 'Test API Documentation',
description: 'This is a sample example of API documentation.'
}
};
const server = Hapi.Server({
host: 'localhost',
port: 3000
});
await server.register([
Inert,
Vision,
Blipp,
{
plugin: HapiSwagger,
options: swaggerOptions
}
]);
server.route({
method: 'GET',
path: `/api/v1.0/data`,
options: {
handler: () => { id: 1 }, // a mock handler
tags: ['api'],
plugins: {
'hapi-swagger': {
responses: {
200: {
description: 'OK',
schema: SimpleModel
}
}
}
}
},
});
await server.start();
return server;
};
ser()
.then((server) => {
console.log(`Server listening on ${server.info.uri}`);
})
.catch((err) => {
console.error(err);
process.exit(1);
});
输出:
...
"definitions": {
"SimpleModel": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"description": "ID",
"format": "int64"
}
},
"required": [
"id"
]
}
}
...
带有自定义类型的示例 2:
const Hapi = require('@hapi/hapi');
const Joi = require('joi');
const Blipp = require('blipp');
const Inert = require('@hapi/inert');
const Vision = require('@hapi/vision');
const HapiSwagger = require('hapi-swagger');
const HapiSwaggerProperties = require('hapi-swagger/lib/properties');
const custom = Joi.extend(joi => ({
type: 'number',
base: Joi.number().$_setFlag('type', 'integer').$_setFlag('format', 'int64'),
rules: {
i32: {
method(first, second) {
return this.$_setFlag('type', 'integer').$_setFlag('format', 'int32');
}
}
}
}));
const _parseNumber = HapiSwaggerProperties.prototype.parseNumber;
HapiSwaggerProperties.prototype.parseNumber = function(property, joiObj) {
let _property = _parseNumber.apply(this, [property, joiObj]);
const describe = joiObj.describe();
if (describe.flags) {
if (describe.flags.format) {
_property.format = describe.flags.format;
}
if (describe.flags.type) {
_property.type = describe.flags.type;
}
}
return _property;
}
const SimpleModel = Joi.object({
id: Joi.number().integer().required().description('ID'),
seconds: custom.number().i32(),
epochSeconds: custom.number(),
}).label('SimpleModel');
const ser = async () => {
const swaggerOptions = {
info: {
title: 'Test API Documentation',
description: 'This is a sample example of API documentation.'
}
};
const server = Hapi.Server({
host: 'localhost',
port: 3000
});
await server.register([
Inert,
Vision,
Blipp,
{
plugin: HapiSwagger,
options: swaggerOptions
}
]);
server.route({
method: 'GET',
path: `/api/v1.0/data`,
options: {
handler: () => { id: 1 }, // a mock handler
tags: ['api'],
plugins: {
'hapi-swagger': {
responses: {
200: {
description: 'OK',
schema: SimpleModel
}
}
}
}
},
});
await server.start();
return server;
};
ser()
.then((server) => {
console.log(`Server listening on ${server.info.uri}`);
})
.catch((err) => {
console.error(err);
process.exit(1);
});
输出:
...
"definitions": {
"SimpleModel": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"description": "ID"
},
"seconds": {
"type": "integer",
"format": "int32"
},
"epochSeconds": {
"type": "integer",
"format": "int64"
}
},
"required": [
"id"
]
}
}
...
带有自定义类型和元属性的示例 3:
const Hapi = require('@hapi/hapi');
const Hoek = require('@hapi/hoek');
const Joi = require('joi');
const Blipp = require('blipp');
const Inert = require('@hapi/inert');
const Vision = require('@hapi/vision');
const HapiSwagger = require('hapi-swagger');
const HapiSwaggerProperties = require('hapi-swagger/lib/properties');
const custom = Joi.extend(joi => ({
type: 'int',
base: Joi.number().meta({
'type': 'integer',
'format': 'int32',
}),
rules: {
i64: {
method(first, second) {
return this.meta({
'type': 'integer',
'format': 'int64',
});
}
}
}
}));
const _parsePropertyMetadata = HapiSwaggerProperties.prototype.parsePropertyMetadata;
HapiSwaggerProperties.prototype.parsePropertyMetadata = function(property, name, parent, joiObj) {
let _property = _parsePropertyMetadata.apply(this, [property, name, parent, joiObj]);
const _type = Hoek.reach(joiObj, 'type');
if (!this.propertyMap[_type]) {
delete _property['x-meta']
}
let xMeta = Hoek.reach(joiObj, '$_terms.metas');
xMeta = xMeta.length > 0 ? xMeta[xMeta.length - 1] : undefined;
if (xMeta) {
if (xMeta.type) {
_property.type = xMeta.type;
}
if (xMeta.format) {
_property.format = xMeta.format;
}
}
return _property;
}
const SimpleModel = Joi.object({
id: Joi.number().integer().required().description('ID'),
seconds: custom.int(),
epochSeconds: custom.int().i64(),
}).label('SimpleModel');
const ser = async () => {
const swaggerOptions = {
info: {
title: 'Test API Documentation',
description: 'This is a sample example of API documentation.'
}
};
const server = Hapi.Server({
host: 'localhost',
port: 3000
});
await server.register([
Inert,
Vision,
Blipp,
{
plugin: HapiSwagger,
options: swaggerOptions
}
]);
server.route({
method: 'GET',
path: `/api/v1.0/data`,
options: {
handler: () => { id: 1 }, // a mock handler
tags: ['api'],
plugins: {
'hapi-swagger': {
responses: {
200: {
description: 'OK',
schema: SimpleModel
}
}
}
}
},
});
await server.start();
return server;
};
ser()
.then((server) => {
console.log(`Server listening on ${server.info.uri}`);
})
.catch((err) => {
console.error(err);
process.exit(1);
});
...
"definitions": {
"SimpleModel": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"description": "ID"
},
"seconds": {
"type": "integer",
"format": "int32"
},
"epochSeconds": {
"type": "integer",
"format": "int64"
}
},
"required": [
"id"
]
}
}
...
有了 and the ,我可以向 hapi-swagger
的存储库提交拉取请求。
因此,从版本 v14.3.0 开始,以下 Joi
模型定义将提供所需的结果
const SimpleModel = Joi.object({
id: Joi.number().integer().required().description('ID').meta({ format: 'int64' })
}).label('SimpleModel');
definitions:
SimpleModel:
type: object
properties:
id:
type: integer
format: int64
description: ID
required:
- id
我有以下 Joi
型号
const SimpleModel = Joi.object({
id: Joi.number().integer().required().description('ID')
}).label('SimpleModel');
该模型正在下面的 @hapi/hapi
路线中使用
{
method: 'GET',
path: `/api/v1.0/data`,
handler: () => { id: 1 }, // a mock handler
config: {
plugins: {
'hapi-swagger': {
responses: {
200: {
description: 'OK',
schema: SimpleModel
}
}
}
}
}
}
上面的模型生成如下面的 swagger 定义
swagger: '2.0'
host: localhost:8080
basePath: /api
info:
title: 'Swagger for SimpleModel'
version: '1.0'
schemes:
- http
- https
paths:
/v1.0/data:
get:
summary: Returns an object
responses:
'200':
schema:
$ref: '#/definitions/SimpleModel'
description: OK
definitions:
SimpleModel:
type: object
properties:
id:
type: integer
description: ID
required:
- id
我想要的是在id
中添加一个额外的字段,即format: int64
,例如
definitions:
SimpleModel:
type: object
properties:
id:
type: integer
format: int64 # <-- new field here!
description: ID
required:
- id
虽然这是由 swagger 支持的,但我找不到任何方法在我的 Joi
模型中定义它,以便它会出现在 hapi-swagger
生成的 swagger 中。
我在网上搜索了好几天,但在网上找不到任何有用的东西,无论是文档还是示例。
有没有办法在 SimpleModel
生成的 swagger 中包含 format: int64
?
package.json
{
"name": "71422008",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"@hapi/hapi": "^20.2.1",
"@hapi/inert": "^6.0.5",
"@hapi/vision": "^6.1.0",
"blipp": "^4.0.2",
"hapi-swagger": "^14.2.5",
"joi": "^17.6.0",
"qs": "^6.10.3"
}
}
index.js
const Hapi = require('@hapi/hapi');
const Joi = require('joi');
const Blipp = require('blipp');
const Inert = require('@hapi/inert');
const Vision = require('@hapi/vision');
const HapiSwagger = require('hapi-swagger');
const HapiSwaggerProperties = require('hapi-swagger/lib/properties');
const _parseNumber = HapiSwaggerProperties.prototype.parseNumber;
HapiSwaggerProperties.prototype.parseNumber = function(property, joiObj) {
let _property = _parseNumber.apply(this, [property, joiObj]);
_property.format = 'int64';
return _property;
}
const SimpleModel = Joi.object({
id: Joi.number().integer().required().description('ID')
}).label('SimpleModel');
const ser = async () => {
const swaggerOptions = {
info: {
title: 'Test API Documentation',
description: 'This is a sample example of API documentation.'
}
};
const server = Hapi.Server({
host: 'localhost',
port: 3000
});
await server.register([
Inert,
Vision,
Blipp,
{
plugin: HapiSwagger,
options: swaggerOptions
}
]);
server.route({
method: 'GET',
path: `/api/v1.0/data`,
options: {
handler: () => { id: 1 }, // a mock handler
tags: ['api'],
plugins: {
'hapi-swagger': {
responses: {
200: {
description: 'OK',
schema: SimpleModel
}
}
}
}
},
});
await server.start();
return server;
};
ser()
.then((server) => {
console.log(`Server listening on ${server.info.uri}`);
})
.catch((err) => {
console.error(err);
process.exit(1);
});
输出:
...
"definitions": {
"SimpleModel": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"description": "ID",
"format": "int64"
}
},
"required": [
"id"
]
}
}
...
带有自定义类型的示例 2:
const Hapi = require('@hapi/hapi');
const Joi = require('joi');
const Blipp = require('blipp');
const Inert = require('@hapi/inert');
const Vision = require('@hapi/vision');
const HapiSwagger = require('hapi-swagger');
const HapiSwaggerProperties = require('hapi-swagger/lib/properties');
const custom = Joi.extend(joi => ({
type: 'number',
base: Joi.number().$_setFlag('type', 'integer').$_setFlag('format', 'int64'),
rules: {
i32: {
method(first, second) {
return this.$_setFlag('type', 'integer').$_setFlag('format', 'int32');
}
}
}
}));
const _parseNumber = HapiSwaggerProperties.prototype.parseNumber;
HapiSwaggerProperties.prototype.parseNumber = function(property, joiObj) {
let _property = _parseNumber.apply(this, [property, joiObj]);
const describe = joiObj.describe();
if (describe.flags) {
if (describe.flags.format) {
_property.format = describe.flags.format;
}
if (describe.flags.type) {
_property.type = describe.flags.type;
}
}
return _property;
}
const SimpleModel = Joi.object({
id: Joi.number().integer().required().description('ID'),
seconds: custom.number().i32(),
epochSeconds: custom.number(),
}).label('SimpleModel');
const ser = async () => {
const swaggerOptions = {
info: {
title: 'Test API Documentation',
description: 'This is a sample example of API documentation.'
}
};
const server = Hapi.Server({
host: 'localhost',
port: 3000
});
await server.register([
Inert,
Vision,
Blipp,
{
plugin: HapiSwagger,
options: swaggerOptions
}
]);
server.route({
method: 'GET',
path: `/api/v1.0/data`,
options: {
handler: () => { id: 1 }, // a mock handler
tags: ['api'],
plugins: {
'hapi-swagger': {
responses: {
200: {
description: 'OK',
schema: SimpleModel
}
}
}
}
},
});
await server.start();
return server;
};
ser()
.then((server) => {
console.log(`Server listening on ${server.info.uri}`);
})
.catch((err) => {
console.error(err);
process.exit(1);
});
输出:
...
"definitions": {
"SimpleModel": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"description": "ID"
},
"seconds": {
"type": "integer",
"format": "int32"
},
"epochSeconds": {
"type": "integer",
"format": "int64"
}
},
"required": [
"id"
]
}
}
...
带有自定义类型和元属性的示例 3:
const Hapi = require('@hapi/hapi');
const Hoek = require('@hapi/hoek');
const Joi = require('joi');
const Blipp = require('blipp');
const Inert = require('@hapi/inert');
const Vision = require('@hapi/vision');
const HapiSwagger = require('hapi-swagger');
const HapiSwaggerProperties = require('hapi-swagger/lib/properties');
const custom = Joi.extend(joi => ({
type: 'int',
base: Joi.number().meta({
'type': 'integer',
'format': 'int32',
}),
rules: {
i64: {
method(first, second) {
return this.meta({
'type': 'integer',
'format': 'int64',
});
}
}
}
}));
const _parsePropertyMetadata = HapiSwaggerProperties.prototype.parsePropertyMetadata;
HapiSwaggerProperties.prototype.parsePropertyMetadata = function(property, name, parent, joiObj) {
let _property = _parsePropertyMetadata.apply(this, [property, name, parent, joiObj]);
const _type = Hoek.reach(joiObj, 'type');
if (!this.propertyMap[_type]) {
delete _property['x-meta']
}
let xMeta = Hoek.reach(joiObj, '$_terms.metas');
xMeta = xMeta.length > 0 ? xMeta[xMeta.length - 1] : undefined;
if (xMeta) {
if (xMeta.type) {
_property.type = xMeta.type;
}
if (xMeta.format) {
_property.format = xMeta.format;
}
}
return _property;
}
const SimpleModel = Joi.object({
id: Joi.number().integer().required().description('ID'),
seconds: custom.int(),
epochSeconds: custom.int().i64(),
}).label('SimpleModel');
const ser = async () => {
const swaggerOptions = {
info: {
title: 'Test API Documentation',
description: 'This is a sample example of API documentation.'
}
};
const server = Hapi.Server({
host: 'localhost',
port: 3000
});
await server.register([
Inert,
Vision,
Blipp,
{
plugin: HapiSwagger,
options: swaggerOptions
}
]);
server.route({
method: 'GET',
path: `/api/v1.0/data`,
options: {
handler: () => { id: 1 }, // a mock handler
tags: ['api'],
plugins: {
'hapi-swagger': {
responses: {
200: {
description: 'OK',
schema: SimpleModel
}
}
}
}
},
});
await server.start();
return server;
};
ser()
.then((server) => {
console.log(`Server listening on ${server.info.uri}`);
})
.catch((err) => {
console.error(err);
process.exit(1);
});
...
"definitions": {
"SimpleModel": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"description": "ID"
},
"seconds": {
"type": "integer",
"format": "int32"
},
"epochSeconds": {
"type": "integer",
"format": "int64"
}
},
"required": [
"id"
]
}
}
...
有了 hapi-swagger
的存储库提交拉取请求。
因此,从版本 v14.3.0 开始,以下 Joi
模型定义将提供所需的结果
const SimpleModel = Joi.object({
id: Joi.number().integer().required().description('ID').meta({ format: 'int64' })
}).label('SimpleModel');
definitions:
SimpleModel:
type: object
properties:
id:
type: integer
format: int64
description: ID
required:
- id