JSON to PHP DTO
Convert a JSON sample into readonly PHP 8.1/8.2 DTO classes with fromArray/toArray methods, nested objects and arrays named, live in your browser.
Generated files
Generated files appear here.
Diagnostics appear here after you paste your input.
Processed locally in your browser. Your data never leaves your device.
About this JSON to PHP DTO converter
Paste a JSON sample and get readonly PHP value objects: one class per object shape, one file per class, with a typed constructor and explicit fromArray/toArray methods. This page is the PHP output of the JSON to Types studio; TypeScript and Zod are one click away and use the same inference.
A worked example
This JSON:
{
"id": 1,
"name": "Ada",
"nickname": null
}becomes App/Data/Root.php (PHP 8.2):
final readonly class Root
{
public function __construct(
public int|float $id,
public string $name,
public mixed $nickname
) {}
public static function fromArray(array $data): self
{
return new self(
id: $data['id'],
name: $data['name'],
nickname: $data['nickname']
);
}
public function toArray(): array
{
return [
'id' => $this->id,
'name' => $this->name,
'nickname' => $this->nickname,
];
}
}nickname is typed mixed because it was only ever seen as null: there is nothing to infer a real type from, and the diagnostics say so.
How to use it
- Paste JSON, drop a file, or load an example.
- Set the namespace and pick PHP 8.1 or 8.2.
- Copy each class, or download them all as one ZIP that mirrors the namespace.
Frequently asked questions
- Why explicit fromArray/toArray methods instead of attributes?
- So the mapping between a JSON key and a PHP property is always visible in the generated code, never hidden behind a naming convention or an attribute a reader would have to look up elsewhere — the same posture as this site's Laravel and Prisma generators. fromArray(array $data): self builds the object from decoded JSON; toArray(): array reverses it exactly.
- Why is a JSON number typed int|float?
- JSON does not distinguish a whole number from a decimal one, and PHP with declare(strict_types=1) enforces the difference at the type level. Typing it int only would throw a TypeError the first time the API sent 4.5. int|float is a real PHP union type and accepts either.
- PHP 8.1 or 8.2?
- Both are supported. PHP 8.2 can mark the whole class readonly (final readonly class) once; PHP 8.1, which does not have class-level readonly, gets readonly written on each property instead. Everything else in the file is identical.
- What if a key is sometimes missing versus sometimes null?
- Either way the property becomes nullable with a null default, so fromArray never fails when the key is absent: $data['key'] ?? null. This is a deliberate simplification — PHP has no separate concept of "optional but never null" for a promoted constructor property with a default.
- How does it handle a class name namespace, and a name like list or class?
- Set the namespace in the options; it also becomes the output folder (App\Data becomes App/Data/ClassName.php). A JSON object whose name would collide with a PHP reserved word (list, class, ...) is generated with a Dto suffix instead, and every such rename is listed in the diagnostics.