Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- [Multipart and Binary Bodies](multipart_and_binary.md)
- [Response Headers](response_headers.md)
- [Rust Generator Configuration](rust_config.md)
- [Go Generator Configuration](go_config.md)
- [TypeScript Generator Configuration](ts_config.md)
- [Python Generator Configuration](python_config.md)
- [Java Generator Configuration](java_config.md)
Expand Down
58 changes: 58 additions & 0 deletions docs/src/go_config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Go Generator Configuration

```toml
[go-http]
module_path = "example.com/sdk"
all_of_strategy = "composed"
```

## Object and map composition

The default `composed` policy retains named object members as embedded Go fields
and gives anonymous map members named storage such as `AdditionalProperties`.
Generated JSON methods combine the members into one flat wire object rather
than inheriting one embedded member's JSON methods and losing its siblings.

```go
value := models.Pair{
Base: models.Base{KnownField: "fixed"},
Other: models.Other{OtherField: 7},
}
// json.Marshal(value): {"known_field":"fixed","other_field":7}
```

Existing named member entrypoints and promoted fields remain available. Repeated
member names or map-storage collisions receive numeric suffixes. Aliases and
nested object compositions are followed without rewriting ordinary model codecs.

On reading, each member receives its own declared keys and globally unknown keys.
A sibling's declared keys are not duplicated into extension storage, so editing a
named field does not leave stale values in a map member. Typed members retain their
native `encoding/json` behavior. If member writes produce different JSON encodings
for the same key, marshaling returns an error instead of silently overwriting data.

This is not a complete JSON Schema validator. It uses retained IR object facts and
conservative representation compatibility; ordinary member validation, optional
fields, null behavior and dynamic `any` number conversion remain unchanged.
In particular, `any` entries still follow Go's native floating-point conventions.
It does not infer missing shared-lowering facts or redesign ordinary dictionary
codecs.

## Raw escape hatch

Set `all_of_strategy = "raw"` to emit every intersection as an alias of
`json.RawMessage`, preserving JSON kinds, nulls and exact numeric literals without
typed member selection. The same raw representation is the default fallback for
non-object intersections, unproductive composition cycles and object/map types
that cannot be conservatively composed. No unconditional generation error or
invalid anonymous-map embedding is introduced for these shapes.

```bash
openapi-nexus generate --input api.yaml --output sdk --generators go-http \
--generator-config go-http.all_of_strategy=raw
```

Raw values intentionally do not enforce intersection constraints. Use them when
wire preservation is more useful than inferred typed composition. This policy
does not change untagged unions, ordinary objects, other generators or generated
dependencies.
10 changes: 9 additions & 1 deletion just/golden-go.just
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,13 @@ set working-directory := '..'
UPDATE_GOLDEN=1 cargo test --test golden_tests_go_http -- --nocapture

# Compile-check Go goldens with go build
@build:
@build: test
./scripts/golden-build-go.sh

# Generate fresh dependencies before ordinary Go consumer execution.
@prepare:
bash ./scripts/generate-go-client-fixtures.sh

@test: prepare
go -C tests/generated-clients/go/composition test ./...
go -C tests/generated-clients/go/raw test ./...
24 changes: 24 additions & 0 deletions scripts/generate-go-client-fixtures.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env bash
set -euo pipefail

root="$(cd "$(dirname "$0")/.." && pwd)"
project="$root/tests/generated-clients/go"
while read -r name fixture strategy; do
case "$name" in
""|\#*) continue ;;
*[!a-zA-Z0-9_-]*) echo "invalid fixture name: $name" >&2; exit 1 ;;
esac
output="$project/generated/$name"
options=(--config "$root/tests/generated-clients/config.toml"
--input "$root/tests/fixtures/$fixture" --output "$output" --generators go-http)
if [ -n "$strategy" ]; then
case "$strategy" in
composed|raw) ;;
*) echo "invalid allOf strategy: $strategy" >&2; exit 1 ;;
esac
options+=(--generator-config "go-http.all_of_strategy=$strategy")
fi
# Only these fixed, ignored fixture output directories are disposable.
rm -rf "$output"
cargo run --quiet --manifest-path "$root/Cargo.toml" --bin openapi-nexus -- generate "${options[@]}"
done < "$project/fixtures.txt"
1 change: 1 addition & 0 deletions src/generators/go/http/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ impl GoHttpCodeGenerator {
&module_path,
&header,
&request_inputs,
self.config.all_of_strategy,
)?);

// APIs
Expand Down
Loading
Loading