0

I'm trying to validate to following json:

{
    "variants": [
        {
            "variant_code": "1",
            "price": 12,
            "discount": 12,
            "height": 1,
            "longitude": 1,
            "width": 1,
            "weight": 1,
            "package_height": 1,
            "package_longitude": 1,
            "package_width": 1,
            "package_weight": 11,
            "stock": 1
        },
        {
            "variant_code": "2",
            "price": 12,
            "discount": 12,
            "height": 1,
            "longitude": 1,
            "width": 1,
            "weight": 1,
            "package_height": 1,
            "package_longitude": 1,
            "package_width": 1,
            "package_weight": 11,
            "stock": 1
        },
        {
            "variant_code": "3",
            "price": 12,
            "discount": 12,
            "height": 1,
            "longitude": 1,
            "width": 1,
            "weight": 1,
            "package_height": 1,
            "package_longitude": 1,
            "package_width": 1,
            "package_weight": 11,
            "stock": 1
        }
    ]
}

I can't find a way to validate it, I've tried to following methods:

$this->validator->validate(
            $request, [
                        "variants" => v::arrayVal()->each(
                            v::key("variant_code", v::stringVal()->notEmpty()->length(1, 100)),
                            v::key("stock", v::intVal()->notOptional()),
                            v::key("price", v::numericVal()->notEmpty()),
                            v::key("discount", v::numericVal()->notEmpty()),
                            v::key("weight", v::numericVal()->notEmpty()),
                            v::key("width", v::numericVal()->notEmpty()),
                            v::key("height", v::numericVal()->notEmpty()),
                            v::key("longitude", v::numericVal()->notEmpty()),
                            v::key("package_weight", v::numericVal()->notEmpty()),
                            v::key("package_width", v::numericVal()->notEmpty()),
                            v::key("package_longitude", v::numericVal()->notEmpty()),
                            v::key("package_height", v::numericVal()->notEmpty())
                        )
                    ]
        );

But it just validates the first key "variant_code" of each relative array. I also tried this:

$this->validator->validate(
            $request, [
                        "variants" => v::arrayVal()->each(
                            v::keySet(
                                v::key("variant_code", v::stringVal()->notEmpty()->length(1, 100)),
                                v::key("stock", v::intVal()->notOptional()),
                                v::key("price", v::numericVal()->notEmpty()),
                                v::key("discount", v::numericVal()->notEmpty()),
                                v::key("weight", v::numericVal()->notEmpty()),
                                v::key("width", v::numericVal()->notEmpty()),
                                v::key("height", v::numericVal()->notEmpty()),
                                v::key("longitude", v::numericVal()->notEmpty()),
                                v::key("package_weight", v::numericVal()->notEmpty()),
                                v::key("package_width", v::numericVal()->notEmpty()),
                                v::key("package_longitude", v::numericVal()->notEmpty()),
                                v::key("package_height", v::numericVal()->notEmpty())
                            )
                        )
                    ]
        );

But it throws the following error:

{
        "variants": {
            "variants": "Must have keys `{ \"variant_code\", \"stock\", \"price\", \"discount\", ... }`"
        }

I've also tryied many other ways unsuccessfully. I'm working with Respect/Validation version 2.0 and PHP version 7.4. Anyone knows how to do it, with respect/validation?(I already know how to do it manually). Thank you.

1 Answers1

0

The problem here is the product_image_id key that is required by your rules but it's not present in the data you're trying to validate.

What I tried:

$string = file_get_contents(__DIR__ . "./data.json");
$json = json_decode($string, true);

function validate($data) {
    v::arrayVal()->each(
        v::keySet(
            v::key("variant_code", v::stringVal()->notEmpty()->length(1, 100)),
            v::key("product_image_id", v::optional(v::intVal())), // This key is missing in the data.json file
            v::key("stock", v::intVal()->notOptional()),
            v::key("price", v::numericVal()->notEmpty()),
            v::key("discount", v::numericVal()->notEmpty()),
            v::key("weight", v::numericVal()->notEmpty()),
            v::key("width", v::numericVal()->notEmpty()),
            v::key("height", v::numericVal()->notEmpty()),
            v::key("longitude", v::numericVal()->notEmpty()),
            v::key("package_weight", v::numericVal()->notEmpty()),
            v::key("package_width", v::numericVal()->notEmpty()),
            v::key("package_longitude", v::numericVal()->notEmpty()),
            v::key("package_height", v::numericVal()->notEmpty())
        )
    )->assert($data);
}

try {
    /*
    $array = [
        [
            "variant_code" => "qwerty"
        ]
    ];
    $result = validate($array);
    */

    validate($json["variants"]);
    echo ("Validation ok");
} catch(NestedValidationException $exception) {
    echo($exception->getFullMessage());
    echo ("Validation error");
}

data.json file:

{
    "variants": [
        {
            "variant_code": "1",
            "price": 12,
            "discount": 12,
            "height": 1,
            "longitude": 1,
            "width": 1,
            "weight": 1,
            "package_height": 1,
            "package_longitude": 1,
            "package_width": 1,
            "package_weight": 11,
            "stock": 1
        },
        {
            "variant_code": "2",
            "price": 12,
            "discount": 12,
            "height": 1,
            "longitude": 1,
            "width": 1,
            "weight": 1,
            "package_height": 1,
            "package_longitude": 1,
            "package_width": 1,
            "package_weight": 11,
            "stock": 1
        },
        {
            "variant_code": "3",
            "price": 12,
            "discount": 12,
            "height": 1,
            "longitude": 1,
            "width": 1,
            "weight": 1,
            "package_height": 1,
            "package_longitude": 1,
            "package_width": 1,
            "package_weight": 11,
            "stock": 1
        }
    ]
}

You can check my complete code here.

Davide Pastore
  • 8,317
  • 10
  • 37
  • 49
  • I made a mistake copy/pasting, even if I remove the key it doesn't work, check that the error is saying the more keys are missing, not just product_image_id. Are you sure that your code work? – Francesc Arolas May 17 '21 at 09:26
  • @FrancescArolas, yes, I think this is the expected behavior, since a `KeySet` is a group of rules. You can check [its implementation](https://github.com/Respect/Validation/blob/2.0.17/library/Rules/KeySet.php) and the [related exception](https://github.com/Respect/Validation/blob/2.0.17/library/Exceptions/KeySetException.php). – Davide Pastore May 18 '21 at 08:08