Skip to content

Preserve empty JSON Schema object maps in FunctionDeclaration parameters #233

@chubes4

Description

@chubes4

Description

FunctionDeclaration accepts JSON Schema-like parameter definitions, but empty object-map fields inside those schemas currently serialize as JSON arrays. In PHP, callers naturally represent an empty object map as [], but JSON Schema fields such as properties are object maps and should serialize as {} when empty.

This can make an otherwise valid function parameter schema invalid by the time a provider request body is JSON encoded.

Minimal reproduction

use WordPress\AiClient\Tools\DTO\FunctionDeclaration;

$declaration = new FunctionDeclaration(
    'inspectObject',
    'Inspects an object with optional nested metadata',
    [
        'type' => 'object',
        'properties' => [
            'metadata' => [
                'type' => 'object',
                'properties' => [],
            ],
        ],
    ]
);

echo json_encode($declaration, JSON_THROW_ON_ERROR);

Actual behavior

The nested JSON Schema object map is emitted as a JSON array:

{
  "name": "inspectObject",
  "description": "Inspects an object with optional nested metadata",
  "parameters": {
    "type": "object",
    "properties": {
      "metadata": {
        "type": "object",
        "properties": []
      }
    }
  }
}

Expected behavior

JSON Schema object-map fields should preserve object semantics when empty:

{
  "name": "inspectObject",
  "description": "Inspects an object with optional nested metadata",
  "parameters": {
    "type": "object",
    "properties": {
      "metadata": {
        "type": "object",
        "properties": {}
      }
    }
  }
}

Evidence

I added a focused PHPUnit repro locally on trunk:

public function testJsonSerializationPreservesEmptySchemaObjectMaps(): void
{
    $declaration = new FunctionDeclaration(
        'inspectObject',
        'Inspects an object with optional nested metadata',
        [
            'type' => 'object',
            'properties' => [
                'metadata' => [
                    'type' => 'object',
                    'properties' => [],
                ],
            ],
        ]
    );

    $json = json_encode($declaration, JSON_THROW_ON_ERROR);

    $this->assertStringContainsString('"properties":{', $json);
    $this->assertStringNotContainsString('"properties":[]', $json);
}

It fails on current trunk:

Failed asserting that
'{"name":"inspectObject","description":"Inspects an object with optional nested metadata","parameters":{"type":"object","properties":{"metadata":{"type":"object","properties":[]}}}}'
does not contain ""properties":[]".

Tests: 1, Assertions: 2, Failures: 1.

The full FunctionDeclarationTest file also only fails this added assertion:

Tests: 15, Assertions: 56, Failures: 1.

Why this likely belongs in the client abstraction

This is provider-agnostic. The issue is not that one provider has a special rule; it is that FunctionDeclaration stores JSON Schema parameter definitions in PHP arrays, and PHP arrays do not preserve empty object-map semantics during JSON encoding.

The affected concept is shared by all providers that consume FunctionDeclaration parameters. Installed provider code paths also commonly embed raw getParameters() or toArray() output into request payloads, so individual providers can encounter the same empty-map serialization issue.

Related

This is adjacent to #229 because both involve JSON Schema payload correctness, but it is not the same bug. #229 is about the OpenAI-compatible structured-output envelope. This issue is about preserving JSON Schema object-map semantics inside FunctionDeclaration parameters.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions