1

I have asked this before at Stackoverflow, now I'm here to be more wp specific and bring more context - as I did some advance on this.

Seeing this use of oneOf has made me change my schema to this structure below:

array(
    'type'         => 'object',
    'show_in_rest' => array(
        'schema' => array(
            'type'       => 'object',
            'properties' => array(
                'tipo' => array(
                    'type'  => 'string',
                    'name'  => 'tipo',
                    'enum'  => array(
                        '...',
                    ),
                ),
                'data' => array(
                    'type'   => 'array',
                    'items'  => array(
                        'type'  => 'object',
                        'oneOf' => array(
                            array(
                                'properties'           => array(
                                    'dia'         => array(
                                        'type'        => 'string',
                                        'name'        => 'dia',
                                    ),
                                    'hora_inicio' => array(
                                        'type'        => 'string',
                                        'name'        => 'hora_inicio',
                                    ),
                                    'hora_fim'    => array(
                                        'type'        => 'string',
                                        'name'        => 'hora_fim',
                                    ),
                                ),
                                'name'                 => 'data_unica',
                                'title'                => 'Data única',
                            ),
                            array(
                                'properties'           => array(
                                    'periodicidade' => array(
                                        'type'        => 'string',
                                        'name'        => 'periodicidade',
                                        'enum'        => array(
                                            '...'
                                        ),
                                    ),
                                    'dia_inicial'   => array(
                                        'type'        => 'string',
                                        'name'        => 'dia_inicial',
                                    ),
                                    'dia_final'     => array(
                                        'type'        => 'string',
                                        'name'        => 'dia_final',
                                    ),
                                    'hora_inicial'  => array(
                                        'type'   => 'string',
                                        'name'   => 'hora_inicial',
                                    ),
                                    'hora_final'    => array(
                                        'type'   => 'string',
                                        'name'   => 'hora_final',
                                    ),
                                ),
                                'name'                 => 'data_corrente',
                                'title'                => 'Data corrente',
                            ),
                        ),
                    ),
                ),
            ),
        ),
    ),
);

The request is:

meta: {
    "datas": {
        "tipo": "UNICA",
        "data": [{
            "dia": "2022-10-21",
            "hora_inicio": "",
            "hora_fim": ""
        }]
    }
}

And the response:

{
    "code": "rest_additional_properties_forbidden",
    "message": "dia is not a valid property of Object.",
    "data": {
        "status": 400
    }
}

What am I doing wrong?

4
  • It looks like you're specifying this schema in a register_meta() call for a metakey named datas - is that correct? Or is this being used somewhere else? Which endpoint are you sending this request to?
    – bosco
    Jul 25, 2022 at 21:02
  • exacly @bosco, i'm using register_meta and using a block that renders a form and mount that request
    – hgodinho
    Jul 25, 2022 at 22:12
  • Hmmm strange - that looks like a valid use of oneOf to me. The only weird bit I see across the whole schema is using name attributes throughout, which do not serve a purpose in JSON Schema, nor do they in WordPress to the best of my knowledge. One thing you might try is removing "type": "object" from the "items" definition and adding it to each of the possible sub-schemas. I don't have a strong basis for this - I think either is technically valid. Failing that, I will try to replicate this myself in the next few days if no one else sorts it out!
    – bosco
    Jul 25, 2022 at 22:50
  • I'm passing the name attribute to use the same schema to dinamically generate components for the block, but I probably could use the key instead the value for this. My first attempt was without the type for items, but this throws an error in debug.log sayind that meta was registered incorrectly.
    – hgodinho
    Jul 25, 2022 at 23:54

1 Answer 1

2

After some testing in WordPress v6.0.1, it seemed that:

  1. We need to set the (default/initial) type of the data.items to null instead of object. (and yes, the type must be set, or else the API response would be invalidated with many "undefined index" notices)

  2. For each item, i.e. an array in the oneOf or anyOf, set the type to object.

So your data schema should look like this, but I purposely used anyOf (see explanation below):

'data' => array(
    'type'  => 'array',
    'items' => array(
        'type'  => null,
        'anyOf' => array(
            array(
                'type'       => 'object',
                'properties' => array( ... ),
                'title'      => 'Data única',
            ),
            array(
                'type'       => 'object',
                'properties' => array( ... ),
                'title'      => 'Data corrente',
            ),
        ), // end anyOf
    ), // end items
), // end data

And the reason why I did not use oneOf, is because it caused an error with the code rest_one_of_multiple_matches and the message meta.datas[data][0] matches Data única and Data corrente, but should match only one.

  • You could avoid that issue by using unique schemas, e.g. add enum to the dia's schema or change the hora_inicio's type to number, but that is up to you to decide.
5
  • Thanks Sally, I'll try this as soon as I can!
    – hgodinho
    Jul 26, 2022 at 14:00
  • That's it! Thank you Sally. So for the oneOf its not about the propertie's keys, but propertie's schema? Because my schema have different properties inside each of oneOf....
    – hgodinho
    Jul 27, 2022 at 14:23
  • 1
    Yes, but more precisely - the value will be checked against both schemas, and thus for example the string 2022-10-21 resulted in the rest_one_of_multiple_matches error, because that string/value passed the validation for (at least) one of the properties in both your schemas.
    – Sally CJ
    Jul 27, 2022 at 15:22
  • @SallyCJ having to explicitly set 'type' => null seems really nutty to me at a glance - like maybe worthy of a Trac ticket, or issue to include it in the docs somewhere. Did you glean any other insight into that wonkiness?
    – bosco
    Aug 29, 2022 at 17:42
  • Hey @bosco, sorry for the late reply! I agreed that it could be a bug in core, and that the 'type' => null was actually just a workaround 😁 As for the other insight, maybe now in v6.0.2 there is, but back then I (tried; however I) couldn't find a better workaround.. So did you end up opening a Trac ticket for this?
    – Sally CJ
    Sep 24, 2022 at 13:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.