Packages
ash_graphql
1.10.0
1.10.0
1.9.4
1.9.3
1.9.2
1.9.1
1.9.0
1.8.5
1.8.4
1.8.3
1.8.2
1.8.1
1.8.0
1.7.17
1.7.16
1.7.15
1.7.14
1.7.13
1.7.12
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.6.0
1.5.1
1.5.0
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.4
1.3.3
1.3.2
1.3.1
1.3.0
1.2.1
1.2.0
1.1.1
1.1.0
1.0.1
1.0.0
1.0.0-rc.5
1.0.0-rc.4
retired
1.0.0-rc.3
1.0.0-rc.2
1.0.0-rc.1
1.0.0-rc.0
0.28.1
0.28.0
0.27.1
0.27.0
0.26.9
0.26.8
0.26.7
0.26.6
0.26.5
0.26.4
0.26.3
0.26.2
0.26.0
0.25.13
0.25.12
0.25.10
0.25.9
0.25.8
0.25.7
0.25.6
0.25.5
0.25.4
0.25.3
0.25.2
0.25.1
0.25.0
0.24.1
0.24.0
0.23.3
0.23.2
0.23.1
0.23.0
0.22.13
0.22.12
0.22.11
0.22.10
0.22.9
0.22.8
0.22.7
0.22.6
0.22.4
0.22.3
0.22.2
0.22.1
0.22.0
0.21.0
retired
0.20.5
0.20.4
0.20.3
0.20.2
0.20.1
0.20.0-rc.3
0.20.0-rc.2
0.20.0-rc.1
0.20.0-rc.0
0.19.0
0.18.0-rc0
0.17.5
0.17.5-rc0
0.17.4
0.17.2
0.17.1
0.17.0
0.16.28
0.16.27
0.16.26
0.16.25
0.16.24
0.16.23
0.16.22
0.16.21
0.16.20
0.16.18-rc5
0.16.18-rc4
0.16.18-rc3
0.16.18-rc2
0.16.18-rc1
0.16.18-rc0
0.16.17
0.16.16
0.16.15
0.16.14
0.16.13
0.16.12
0.16.11
0.16.10
0.16.9
0.16.8
0.16.7
0.16.6
0.16.5
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.10
0.15.9
0.15.8
0.15.7
0.15.6
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.1
0.14.0
0.13.1
0.13.0
0.12.5
0.12.4
0.12.3
0.12.1
0.12.0
0.10.0
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.0
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.3
0.6.2
0.6.1
0.6.0
0.5.0
0.4.0
0.3.2
0.3.1
0.3.0
0.2.1
0.2.0
0.1.3
0.1.2
The extension for building GraphQL APIs with Ash
Current section
Files
Jump to
Current section
Files
documentation/topics/use-struct-types-with-graphql.md
<!--
SPDX-FileCopyrightText: 2020 Zach Daniel
SPDX-License-Identifier: MIT
-->
# Use Struct Types with GraphQL
Custom struct types provide structured GraphQL input validation for standalone data arguments instead of generic JSON strings.
## The Problem
Relationship arguments automatically get structured inputs, but standalone data arguments default to JsonString:
```elixir
# Relationship: Gets structured CreateAddressInput
argument :address, :map
change manage_relationship(:address, type: :direct_control)
# Standalone data: Becomes JsonString (no validation)
argument :metadata, :map
```
## Solution: Custom Struct Types
### Using Ash.TypedStruct (new structures)
```elixir
defmodule MyApp.Types.TicketMetadataType do
use Ash.TypedStruct
typed_struct do
field :priority, :string, allow_nil?: false
field :category, :string, allow_nil?: false
field :tags, {:array, :string}, allow_nil?: true
end
use AshGraphql.Type
@impl true
def graphql_type(_), do: :ticket_metadata
@impl true
def graphql_input_type(_), do: :create_ticket_metadata_input
end
```
### Using NewType (reference existing resources)
```elixir
defmodule MyApp.Types.TicketMetadataType do
use Ash.Type.NewType,
subtype_of: :struct,
constraints: [
instance_of: MyApp.TicketMetadata
]
use AshGraphql.Type
@impl true
def graphql_type(_), do: :ticket_metadata
@impl true
def graphql_input_type(_), do: :create_ticket_metadata_input
end
```
**Key Differences:**
- **TypedStruct**: Define fields manually, full control, requires manual sync
- **NewType**: Auto-inherits from resource, stays in sync, less flexible
### Use in your resource
```elixir
defmodule MyApp.Ticket do
actions do
action :add_metadata do
argument :metadata, MyApp.Types.TicketMetadataType,
allow_nil?: false
end
end
end
```
## Result
```graphql
input AddMetadataInput {
metadata: CreateTicketMetadataInput! # Structured input
}
input CreateTicketMetadataInput {
priority: String!
category: String!
tags: [String!]
}
```
## Common Issues & Solutions
**Still seeing JsonString?**
1. Ensure `graphql_input_type` references an existing input type
2. Target resource must have GraphQL mutations defined:
```elixir
graphql do
mutations do
create :create_ticket_metadata, :create
end
end
```
3. Run `mix ash.codegen` to regenerate schema
**Note:** Using `:struct` with `instance_of` directly also falls back to JsonString when used as an input. Always wrap in a custom type for structured validation.