使用JSON模式免费模拟API

JSON::Schema::ToJSON是一个模块,它接受一个JSON模式,并生成符合该模式的 数据结构。以下是一个快速脚本,用于根据模式生成数据结构:

#!/usr/bin/perl
# gen-json - create json from a schema filepath
use Data::Dumper;
use JSON::Schema::ToJSON;

my $generator = JSON::Schema::ToJSON->new();
my $schema    = do { local($/);<> }; # slurp the filepath in @ARGV
my $data      = $generator->json_schema_to_json(schema_str => $schema);

print Dumper($data);

要运行它,我需要传入一个JSON模式的文件路径,在这个例子中,user.json描述了一个Web应用用户。

$ ./gen-json user.json
$VAR1 = {
      'email_address' => 'HfeiJzddxVTg@AspFqfgUKivV.com',
      'birthdate' => '2014-01-14T00:59:43.000Z',
      'active' => bless( do{\(my $o = 0)}, 'JSON::PP::Boolean' ),
      'cell_phone_number' => '043 185 8956',
      'roles' => [
                   'manager',
                   'trainer',
                   'admin'
                 ],
      'display_name' => 'Pswgfkjzdc',
      'password' => 'QI0RQDR9A7W2EtuNHaQKvBFQp67oO0Ld',
      'login' => '7oRSCeREi9sWm',
      'full_name' => 'Oiqmqdr Frfxrzkzfjn',
    };

脚本创建了一个新的JSON::Schema::ToJSON对象,名为$generator,将JSON模式吸入到$schema中,并将生成的数据结构分配给$data。然后,通过Data::Dumper$data格式化输出到STDOUT。注意,打印到终端的数据是符合规范但不真实的。

模拟API

使用JSON模式描述API端点是Swagger的常见做法。Swagger将使用模式生成文档,并提供请求/响应测试工具。我们可以通过使用它们来模拟API端点来使JSON模式更加有用。想象一下,你已经定义了一个API,但还没有构建它:你可以创建API端点,并返回由JSON::Schema::ToJSON模拟的数据,这样前端开发就可以在不等待后端准备好时开始。

假设我们有一个以下Swagger文档(一个JSON模式),它定义了一个单个API路由/user

{
  "swagger": "2.0",
  "schemes": [
    "https"
  ],
  "produces": [
    "application/json"
  ],
  "paths": {
    "/user": {
      "get": {
        "summary": "returns a user for a given id",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Objects matching the search term",
            "schema": {
              "type": "object",
              "properties": {
                "login": {
                  "type": "string",
                  "pattern": "[0-9A-Za-z]{5,32}"
                },
                "full_name": {
                  "type": "string",
                  "pattern": "[A-Z][a-z]{3,10} [A-Z][a-z]{3,20}"
                },
                "display_name": {
                  "type": "string",
                  "pattern": "[A-Z][a-z]{3,10}"
                },
                "birthdate": {
                  "type": "string",
                  "format": "date-time"
                },
                "email_address": {
                  "type": "string",
                  "format": "email"
                },
                "cell_phone_number": {
                  "type": "string",
                  "pattern": "\\d{3} \\d{3} \\d{4}"
                },
                "password": {
                  "type": "string",
                  "pattern": "[0-9A-Za-z]{8,32}"
                },
                "roles": {
                  "type": "array",
                  "minItems": 1,
                  "maxItems": 4,
                  "uniqueItems": true,
                  "items": {
                    "type": "string",
                    "enum": [ "admin", "manager", "trainer", "member" ]
                  }
                },
                "active": {
                  "type": "boolean"
                }
              }
            }
          }
        }
      }
    }
  }
}

这是一个Mojolicious::Lite应用,用于提供模拟的路由。

use Mojolicious::Lite;
use JSON::XS 'decode_json';
use JSON::Schema::ToJSON;

my $generator  = JSON::Schema::ToJSON->new();
my $json       = do { open my $fh, '<', 'swaggerdoc.json'; local($/);<$fh> };
my $swaggerdoc = decode_json($json);

get '/user' => sub {
  my $self = shift;
  my $route_def = $swaggerdoc->{paths}{'/user'}{get}{responses}{200}{schema};
  my $response = $generator->json_schema_to_json(schema => $route_def);
  $self->render(json => $response);
};

app->start;

此应用在启动时吸入并解码Swagger文档,将结果保存到$swaggerdoc中,并声明一个/user路由,该路由从$swaggerdoc中提取API定义,并使用JSON::Schema::ToJSON生成响应,并将其呈现。让我们测试一下这个应用。

$ hypnotoad user-app.pl
[Wed Sep 20 14:19:49 2017] [info] Listening at "http://*:8080"
Server available at http://127.0.0.1:8080

$ curl localhost:8080/user
{"active":false,"birthdate":"2009-08-30T17:47:32.000Z","cell_phone_number":"254 403 0133","display_name":"Nyzhoyp","email_address":"gEyRQXRPrlzL@CvuRitFtArXv.com","full_name":"Wmpgrd Bnaazxguekqtuezlu","login":"oAxgIvYQfbRmWHq4WifclhQxAI","password":"99wciSr8V","roles":["member","trainer","manager"]}

$ hypnotoad -s user-app.pl
Stopping Hypnotoad server 2177 gracefully.

首先,我用hypnotoad将应用放入后台。接下来,我使用curl测试端点,并正确返回了用户JSON。最后,我再次用hypnotoad停止应用。看起来不错!

限制

当使用JSON::Schema::ToJSON时,我遇到了一些限制。一个我已经提到了:它生成符合规范但不是真实的数据。这可能导致问题,如果您的对象属性有相互依赖关系,例如,first_name应该是full_name的子串。或者当生成日期时,有时随机日期时间不够精确:对于出生日期的真实日期,您可能希望某人是在10到80年前出生的。这个问题可以通过在JSON模式中使用正则表达式定义或使用JSON::Schema::ToJSONexample_key功能来部分缓解。

另一个问题是由于JSON模式本身的限制造成的:您可能无法以API返回的格式生成数据,例如,没有日期格式,只有日期时间。

但这些是微小的限制,我仍然坚信JSON::Schema::ToJSON是一种很好的方法,可以通过快速生成测试数据和/或模拟API来增强JSON模式的价值。


这篇文章最初发布在PerlTricks.com上。

标签

David Farrell

David是一位职业程序员,他经常推文博客关于代码和编程艺术。

查看他们的文章

反馈

这篇文章有什么问题吗?请通过在GitHub上打开一个问题或拉取请求来帮助我们。