# Three mistakes when converting JSON to types

A copied API body feels like it should turn into types with nothing left over. The converter will draft something. The draft follows a few rules that are easy to miss if you only look at the first row and the green status.

### Mistake 1: expecting every row to shape the interface

Take two objects that do not match:

```json
[{"id":1,"name":"Ada"},{"id":2,"email":"linus@example.com"}]
```

The TypeScript result is only the first object:

```ts
export interface Root {
  id: number;
  name: string;
}
```

The PHP DTO matches that shape: `public int $id` and `public string $name`, each assigned with `?? null`. `email` is not on the class. The Laravel array still contains both rows, so the second row's email survives there. CSV is the format that notices the extra key. Its header is `id,name,email`, the first data row ends with an empty cell, and the second row leaves `name` empty:

```csv
id,name,email
1,Ada,
2,,linus@example.com
```

If you need `email` on the interface, put it on the object you convert, or add the property after the draft.

### Mistake 2: asking CSV for a column per nested field

A nested object stays one cell. For the two-person sample whose meta holds `active`, the CSV the converter writes is:

```csv
id,name,role,meta
1,Ada,engineer,"{""active"":true}"
2,Linus,founder,"{""active"":false}"
```

There is no `active` column. An array at the top level is the same kind of cell: `{"id":1,"tags":[]}` puts `[]` under `tags`. Laravel, by contrast, nests meta as a PHP array, and TypeScript gives it a second interface, `Meta`, with `active: boolean`. The PHP DTO does neither of those. It types meta as `array` and copies the value through.

### Mistake 3: shipping the class or the interface without reading it

The PHP class is always named `DataTransferObject`. The constructor writes `$this->id = $data['id'] ?? null` against `public int $id`. A missing key becomes null in that line. Nested objects do not become child classes.

A key such as `first-name` is quoted in the Laravel array, which is fine for PHP array syntax. The TypeScript line is `first-name: string;` and the PHP property is `public string $first-name;`. Both use the key as a bare name.

Child interfaces drop one trailing s. A property `items` whose first element is an object is typed `Item[]`. A property `status` with an object element is typed `Statu[]`, and the interface is `export interface Statu`.

Invalid JSON does not produce a half result. The output is cleared. `{` shows `Expected property name or '}' in JSON at position 1 (line 1 column 2)`. A trailing comma in `{"a":1,}` shows `Expected double-quoted property name in JSON at position 7 (line 1 column 8)`. Empty input shows `Unexpected end of JSON input`. Fix the text in the formatter at <https://kepttools.com/json-formatter>, then convert again at <https://kepttools.com/json-converter>.

The empty-array cases, the null fields, and the rest of the FAQ are in the guide: <https://kepttools.com/guides/json-to-typescript-php-dto-laravel>
