What this tool does
A JSON sample becomes PHP classes with promoted constructor properties.
{ "id": 1, "firstName": "Ada", "address": { "city": "Paris" } }
<?php
declare(strict_types=1);
class Root
{
public function __construct(
public int $id,
public string $firstName,
public Address $address,
) {
}
}
Property promotion needs PHP 8.0; the readonly toggle needs 8.1. declare(strict_types=1) is there on purpose: without it, PHP would quietly coerce a string into an int parameter and you would lose the check the types were meant to give you.
A renamed property keeps its key
PHP property names are camelCase here, which means a key with a dash or a leading digit does not survive as a name. When that happens, the key is written beside it:
/** JSON key: "content-type" */
public string $contentType,
public int $fooBar,
/** JSON key: "foo-bar" */
public int $fooBar2,
That last pair is the reason: fooBar and foo-bar both want $fooBar, so the second becomes $fooBar2 — and without the comment nothing in the file said which came from which. PHP has no standard mapping attribute to carry it, so a comment does, and only where the name no longer carries the key.
This was a real gap, found while writing this page: PHP was the only one of these generators to lose the key entirely. Go has its tag, Java and C# their annotation, Swift its CodingKeys, Dart its fromJson.
What PHP cannot narrow
arrayfor every list. The language has no generics;list<string>lives in a PHPStan or Psalm docblock, and which one you use is not something a sample can know.mixedfornulland unknown values. It is the honest type: it accepts everything, anddeclare(strict_types=1)will not save you there. Narrow it as soon as the field has a real type.- A scalar at the root is refused. PHP has no type alias, so
42or"text"has nothing to become.
What a sample cannot say
No property is nullable and none has a default: the document had a value for each. ?string and = null are the edits you make when a second payload shows the key can be absent — and readonly is worth turning on if these objects are meant to be read, not filled in.
Private by design
Everything runs locally in your browser with JavaScript. Your data is never uploaded, which makes the tool safe for sensitive content, and it keeps working offline.