Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:119662 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 96429 invoked from network); 3 Mar 2023 12:19:33 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 3 Mar 2023 12:19:33 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 723EE1804D4 for ; Fri, 3 Mar 2023 04:19:32 -0800 (PST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-1.4 required=5.0 tests=BAYES_00, FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS, HTML_MESSAGE,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS15169 209.85.128.0/17 X-Spam-Virus: No X-Envelope-From: Received: from mail-ed1-f46.google.com (mail-ed1-f46.google.com [209.85.208.46]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Fri, 3 Mar 2023 04:19:32 -0800 (PST) Received: by mail-ed1-f46.google.com with SMTP id o12so9438630edb.9 for ; Fri, 03 Mar 2023 04:19:32 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=4zZr57j9X5eXasYOkfxfZg4wG4bOi+FEUICEQg4Fjyw=; b=QQR5utFrwAJlOLN6XZUi5z0w2v/kDEcv5fRhtgJV7QoleAXRmyINkTa19XqilB2MhJ zD07DJbScp7EbIjBp9XOZZWO0XVddNxZrsdxoPC/IBGoL6xi5Y8QaLMlkv9JV1xtSqsn jl8KAPmk/KBn0JrgTDkOTRGRA1SpJZtotJLknk0ofOKFNbTQUlvz5W62aMCcalT90DzK /sIDgGVQqAd2yrkrlmE+0Zf41M8TsL8jOxaUMyOoRMBtMfyeGJW/mlWjGETcjdjOCPU6 OAoiXVP94b6lPSJ9LcVevcEDgKerECHT3OyIhyuqXgENYKaa+sTxXlTV0Z1Pm9oV0NCN NPxA== X-Gm-Message-State: AO0yUKUmipIWSPvJz1Njt0e5Qh/EBB33kpbWh+bf+X77QbJD3FmyiI/y NrKVmySJMS5XNKwwaBG5HoTvKDChXh4xIQ+tppz2b1jWi7A= X-Google-Smtp-Source: AK7set/8u4dioq7tcQUQ1ILyGKhx11Y3SNnbRyzsijP90gqqcOgBrEoGxsp3nL8HN6X3eR2/zqtVbmQw6r7Jp+y3EVs= X-Received: by 2002:a17:906:b004:b0:90b:167e:304f with SMTP id v4-20020a170906b00400b0090b167e304fmr693289ejy.8.1677845970711; Fri, 03 Mar 2023 04:19:30 -0800 (PST) MIME-Version: 1.0 References: <7e08b0f9-9d30-4ead-8194-2494ecc78e2e@app.fastmail.com> In-Reply-To: <7e08b0f9-9d30-4ead-8194-2494ecc78e2e@app.fastmail.com> Date: Fri, 3 Mar 2023 12:19:19 +0000 Message-ID: To: Larry Garfield Cc: php internals Content-Type: multipart/alternative; boundary="0000000000001276fc05f5fdf548" Subject: Re: [PHP-DEV] RFC Idea - json_validate() validate schema From: bukka@php.net (Jakub Zelenka) --0000000000001276fc05f5fdf548 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi, On Thu, Mar 2, 2023 at 8:30=E2=80=AFPM Larry Garfield wrote: > On Thu, Mar 2, 2023, at 1:31 PM, Jakub Zelenka wrote: > > On Thu, Mar 2, 2023 at 5:53=E2=80=AFPM Rowan Tommins > > wrote: > > > >> On Thu, 2 Mar 2023 at 12:34, Jakub Zelenka wrote: > >> > >> > It's possible that we might decide to stop supporting some drafts if > the > >> > maintenance burden is too big and usage small but I wouldn't see tha= t > as > >> > something that happens often. But essentially you are right that the= re > >> will > >> > be minimum (draft-04 initially) and maximum (latest implemented > draft). > >> > > >> > >> > >> Thinking about this, particularly if there is the ability to install a > PECL > >> extension which supports different versions from the core PHP version, > >> perhaps it would be useful to expose a function or constant that lists > the > >> supported versions, so that code needing a particular version could > check > >> for support directly, rather than having to attempt and catch an > exception? > >> > >> > > That's a good point. I think a constant should be sufficient. I think t= he > > different classes make less sense if $schema is specified as I would > think > > that the $schema should have a priority. So having just default argumen= t > > using the constant for the cases where it's not specified should be > > sufficient IMHO. > > > > Cheers > > > > Jakub > > You mean using the version from the JSON string, and allowing an > override? Like this? > > It should never allow overriding the $schema as it would go against spec so this would be just default if $schema is not specified. Just the default could be overridden. > new JsonSchema($schema_string, version: JsonSchema::DRAFT_4); > > Would be probably called more JsonSchema::VERSION_DRAFT_04 but essentially yeah I was thinking either that or something like just global constant JSON_SCHEMA_VERSION_DRAFT_04 which is currently more convention in json extension. I wouldn't really mind using the class constant though. As I said my main point was that custom defined schema should contain version in the schema - I realise that it might not be used in wild but this is defined as SHOULD in all drafts so we should follow that recommendation in our API design. When this is the case, there is no point for user to explicitly pick the schema class IMO. Another thing to note is that we might want to introduce some sort of a factory method or factory class instead of using constructor because as I said before we would probably like to introduce more sources for schema than just string in the future. It means it could be automatically generated schema from a class so only the class name would be passed or for convenience it could be just passed directly from the assoc array. It is basically pointless to always convert it to string because internally it will just decode the json string to object (stdClass) or more likely array and parse the schema internal representation from that. If we had this, we could maybe introduce a different schema classes as well but it would be more invisible for users and could be just subclasses of JsonSchema or JsonSchema would be just an interface. > I see two issues there. > > 1. If I want to see if DRAFT_6 is available, I have to use defined()[1] > with strings. This is fugly. > > This is a good point as for class with autoloader you don't need strings. Maybe we could also introduce JsonSchema::VERSION_LATEST which would have value of the last supported draft. Then you could check if draft-06 is supported by just doing something like if (JsonSchema::VERSION_LATEST > JsonSchema::VERSION_DRAFT_04) { // at lest draft 06 } else if (JsonSchema::VERSION_LATEST > JsonSchema::VERSION_DRAFT_06) { // at lest draft 07 } else ... We could also support string for the actual version and allowing passing the well defined values for $schema. The it would throw exception if it's not supported. We could even have static method to check whether version is supported and then for example doing something like if (JsonSchema::isVersionSupported(" https://json-schema.org/draft/2020-12/schema")) { ... } > 2. I don't know how to polyfill newer spec versions if I don't want to > wait for internals to get around to adding a new version. > I guess it could be possible to support custom user validators (e.g. instances implementing JsonSchema interface if above concept is used) in the future but it would be of course more limited. That's not something that would happen initially but it might be good design an API with that in mind. So to sum it up, maybe the rough structure could be something like interface JsonSchema { const VERSION_DRAFT_04 =3D 1; const VERSION_DRAFT_06 =3D 2; const VERSION_DRAFT_07 =3D 3; const VERSION_LATEST =3D 3; public function validate(array|stdClass $data): bool; } class JsonSchemaForVersionDraft04 implements JsonSchema { public function validate(array|stdClass $data): bool {} } class JsonSchemaForVersionDraft06 implements JsonSchema { public function validate(array|stdClass $data): bool {} } class JsonSchemaForVersionDraft07 implements JsonSchema { public function validate(array|stdClass $data): bool {} } class JsonSchemaFactory { public static function createFromJsonString(string $jsonString, int|string $version =3D JsonSchema::VERSION_LATEST): JsonSchema {} public static function createFromClasl(string $className, int|string $version =3D JsonSchema::VERSION_LATEST): JsonSchema {} public static function createFromArray(array $schemaData, int|string $version =3D JsonSchema::VERSION_LATEST): JsonSchema {} public static function isVersionSupported(int|string $version): bool {} } Just a draft of course so any ideas how to improve it are welcome. What do you think? Cheers Jakub --0000000000001276fc05f5fdf548--