# Merging AllOf Schemas [Beta]
OpenAPI 3.0 provides several keywords which can be used to combine schemas.  
You can use these keywords to create a complex schema or validate a value against multiple criteria.  
- oneOf – validates the value against exactly one of the subschemas
- allOf – validates the value against all the subschemas
- anyOf – validates the value against any (one or more) of the subschemas

Using these keywords can be useful to describe complex data models but it complicates breaking changes detection.
Consider, for example, the following comparison of two OpenAPI specs:
```
oasdiff breaking data/allof/simple.yaml data/allof/revision.yaml 
```

The result shows one breaking change which is due to a new subschema that was added under allOf. But the new subschema doesn't actually add any new constraints because it is identical to a previously existing subschema, and as such this isn't a breaking change.
You can verify this with a regular diff comparison:
```
diff --side-by-side data/allof/simple.yaml data/allof/revision.yaml
```

In order to reduce such false-positives, oasdiff supports the ability to replace allOf by a merged equivalent before comparing the specs, like this:

```
oasdiff breaking data/allof/simple.yaml data/allof/revision.yaml --flatten-allof
```
In this case no breaking changes are reported, correctly.  
The `--flatten-allof` flag is also supported with `diff`, `changelog` and `summary`.

In order to see how oasdiff merges allOf, you can use the dedicated `flatten` command:
```
oasdiff flatten data/allof/simple.yaml
```

## Source location limitations
When using `--flatten-allof`, source locations (file, line, column) are not available for changes detected in flattened schemas. This is because the merged schema is a new construct that doesn't correspond to a single location in the original file.

The following schema fields are not merged:
- Extensions
- Example
- ExternalDocs
- AllowEmptyValue
- Deprecated
- XML
- Discriminator
- `$defs` (OpenAPI 3.1) — intentionally dropped from the flattened output. `$defs` is a reusable-schema namespace used as the target of `$ref` pointers. After `--flatten-allof` runs, the merged schema has no `$ref`s left to resolve, so the namespace contributes nothing to its semantics. Preserving it would only add noise (and risk silent collisions when two `allOf` subschemas define different things under the same `$defs` key).

## Invalid input handling

The merger is defensive about spec violations — values that would crash the merge or produce nonsense are silently skipped rather than reported. For example, `multipleOf` values that are zero or negative (disallowed by the OpenAPI / JSON Schema spec) are dropped from the merged result. To surface invalid values in your spec rather than rely on the merger swallowing them, validate the spec separately.

## `contains` is over-constrained when subschemas differ (OpenAPI 3.1)

The strict `allOf` semantics for `contains` are *"≥1 array item matches X AND ≥1 item matches Y"* — the two matching items can be different. We can't express that as a single subschema, so when multiple `allOf` siblings each set `contains`, oasdiff merges the subschemas recursively (as if wrapped in `allOf`) and emits a single `contains: Merge(X, Y)`. That is *stricter* than the original: it requires one item to satisfy both X and Y. Arrays the original spec accepts (where X and Y are matched by distinct items) may be rejected after flattening; arrays the original rejects are never accepted. In practice this rarely matters because most specs have at most one `contains` per `allOf` chain.

Please help us improve this feature by providing feedback and reporting issues.
