如何使用phpleague / json-guard验证json的结构

时间:2017-05-20 11:01:29

标签: json validation laravel-5.4

我正在使用Laravel 5.4作为api,并且有一个接受JSON的端点:

{
    "input": {
        "owner": "name of owner",
        "content": [
        ] 
    }
}

我希望只在input中获取JSON并确保它在结构上和基于内容都是有效的。

使用http://json-guard.thephpleague.com及其overview页面中的基本示例,无论我作为输入更改内容,所有内容都会返回有效状态,因此我认为我使用的是错误的。

从他们的例子中我构建了以下内容。它通过验证。问题是我无法让它失败。

路由文件

Route::post('validate', 'TestController@validateJson');

@的TestController validateJson

public function validateJson()
{
    $dereferencer  = \League\JsonReference\Dereferencer::draft4();
    $schema        = json_decode('{ "properties": { "id": { "type": "string", "format": "uri" } } }');
    $data          = json_decode('{ "id": "https://json-guard.dev/schema#" }');

    $validator     = new \League\JsonGuard\Validator($data, $schema);

    if ($validator->fails()) {
        return response($validator->errors());
    }

    return response('all ok');
}

我相信我可能需要使用JSON参考并定义自定义架构,但在我完全理解该示例并使其失败之前,我不想做任何更复杂的事情。

1 个答案:

答案 0 :(得分:0)

  

无论我作为输入改变什么,一切都恢复有效,所以我认为我使用它是错误的。

如果没有看到您尝试输入的示例,很难确切地说出问题所在。由于示例模式验证idstring格式为uri,因此当您提供的字符串不是有效URI时,它应该会失败。以下示例将返回格式错误:

<?php

require __DIR__ . '/vendor/autoload.php';

$schema        = json_decode('{ "properties": { "id": { "type": "string", "format": "uri" } } }');
$data          = json_decode('{ "id": "hello world" }');
$validator     = new \League\JsonGuard\Validator($data, $schema);

echo json_encode($validator->errors(), JSON_PRETTY_PRINT);

JSON Schema的某些部分不直观,您可能不希望通过。

约束仅验证它是否适用于该类型。如果您没有通过对象,则验证将通过,因为properties约束仅适用于对象:

$data = null;
var_dump((new \League\JsonGuard\Validator($data, $schema))->passes()); // true

要使非对象输入失败,您需要指定"type": "object"。请注意,无效的JSON也会发生这种情况,因为json_decode在失败时会返回null

验证也会传递一个空对象:

$data = json_decode('{}');
var_dump((new \League\JsonGuard\Validator($data, $schema))->passes()); // true

要制作所需的属性,您必须使用required关键字。

  

我想在输入中只获取JSON并确保它在结构上和基于内容有效。

此架构应作为起点:

{
    "type": "object",
    "properties": {
        "input": {
            "type": "object",
            "properties": {
                "owner": {
                    "type": "string",
                    "minLength": 1"
                },
                "content": {
                    "type": "array"
                }
            },
            "required": ["owner", "content"],
            "additionalProperties": false
        }
    },
    "required": ["input"],
    "additionalProperties": false
}

我们要求输入是一个对象,它具有输入属性而没有其他属性,并且该输入是具有属性所有者和内容的对象。所有者的minLength规则是防止空字符串传递。

  

我相信我可能需要使用JSON参考并定义自定义架构

你可以编写非常复杂的模式而根本不使用JSON Reference。它只是一种在没有复制和粘贴的情况下重用模式的方法。例如,您可以定义一笔“钱”。架构并将其用于API中的任何金额。

您肯定需要编写自定义架构。该模式取代了您为每个端点编写的Laravel验证规则。