# Extract lists and nested data

Represent repeated page structures as JSON Schema arrays. Makra uses structural coordinates to join sibling fields into rows rather than zipping independently extracted lists by position.

## A listing schema

```python
schema = {
    "type": "object",
    "properties": {
        "products": {
            "type": "array",
            "description": "Products shown in the result list",
            "items": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "The product name",
                    },
                    "price": {
                        "type": "string",
                        "description": "The current selling price",
                    },
                    "detail_url:$link": {
                        "type": "string",
                        "description": "The product detail page link",
                    },
                },
            },
        }
    },
}
```

The array contributes a coordinate dimension. A nested array contributes another one. Makra carries these coordinates from selector execution through assembly.

## Why coordinates matter

Suppose a page has ten products and the fourth product has no price. Extracting ten names and nine prices, then zipping by list index, assigns every later price to the wrong product.

Makra treats a structural position as row identity. The missing price stays `None` in the fourth row. Later prices keep their own row coordinates.

A row exists when any descendant field provides evidence for it. Makra does not discard a real item because one optional field is missing.

## Nested arrays

```python
schema = {
    "type": "object",
    "properties": {
        "categories": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "name": {"type": "string", "description": "Category name"},
                    "products": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "name": {"type": "string", "description": "Product name"},
                                "price": {"type": "string", "description": "Current price"},
                            },
                        },
                    },
                },
            },
        }
    },
}
```

Each product coordinate is scoped to its category coordinate. This prevents an inner list from collapsing across outer rows.

## Diagnose degraded arrays

Inspect warnings for sibling alignment degradation, array coordinate degradation, empty matches, and fallback selector use. A well-formed Python list does not prove correct row identity.

Test sparse rows, optional fields, separators, ads inserted between items, and a page with a different item count. Those cases expose list extractors that work only on one polished page.

Next, [discover a page schema](/markdown/makra-sdk/v0.0.4-beta/extraction/discover-a-page-schema).
