Scalars

Scalar types represent concrete values at the leaves of a query. For example in the following query the name field will resolve to a scalar type (in this case it's a String type):

Query
{
user {
name
}
}
Response
{
"data": {
"user": {
"name": "Patrick"
}
}
}

There are several built-in scalars, and you can define custom scalars too. (Enums are also leaf values.) The built in scalars are:

  • String, maps to Python’s str
  • Int, a signed 32-bit integer, maps to Python’s int
  • Float, a signed double-precision floating-point value, maps to Python’s float
  • Boolean, true or false, maps to Python’s bool
  • ID, a specialised String for representing unique object identifiers
  • Date, an ISO-8601 encoded date
  • DateTime, an ISO-8601 encoded datetime
  • Time, an ISO-8601 encoded time
  • Decimal, a Decimal value serialized as a string
  • UUID, a UUID value serialized as a string

Fields can return built-in scalars by using the Python equivalent:

Python
import datetime
import decimal
import uuid
import strawberry
@strawberry.type
class Product:
id: uuid.UUID
name: str
stock: int
is_available: bool
available_from: datetime.date
same_day_shipping_before: datetime.time
created_at: datetime.datetime
price: decimal.Decimal
Schema
type Product {
id: UUID!
name: String!
stock: Int!
isAvailable: Boolean!
availableFrom: Date!
sameDayShippingBefore: Time!
createdAt: DateTime!
price: Decimal!
}

Scalar types can also be used as inputs:

import datetime
import strawberry
@strawberry.type
class Query:
@strawberry.field
def one_week_from(self, date_input: datetime.date) -> datetime.date:
return date_input + datetime.timedelta(weeks=1)

Custom scalars

You can create custom scalars for your schema to represent specific types in your data model. This can be helpful to let clients know what kind of data they can expect for a particular field.

To define a custom scalar you need to give it a name and functions that tell Strawberry how to serialize and deserialise the type.

For example here is a custom scalar type to represent a Base64 string:

import base64
from typing import NewType
import strawberry
Base64 = strawberry.scalar(
NewType("Base64", bytes),
serialize=lambda v: base64.b64encode(v).decode("utf-8"),
parse_value=lambda v: base64.b64decode(v.encode("utf-8")),
)
@strawberry.type
class Query:
@strawberry.field
def base64(self) -> Base64:
return Base64(b"hi")
schema = strawberry.Schema(Query)
result = schema.execute_sync("{ base64 }")
assert results.data == {"base64": "aGk="}

Example JSONScalar

import json
from typing import Any, NewType
import strawberry
JSONScalar = strawberry.scalar(
NewType("JSONScalar", Any),
serialize=lambda v: v,
parse_value=lambda v: json.loads(v),
description="The GenericScalar scalar type represents a generic GraphQL scalar value that could be: List or Object."
)

Usage:

@strawberry.type
class Query:
@strawberry.field
def data(self, info) -> JSONScalar:
return {"hello": {"a": 1}, "someNumbers": [1, 2, 3]}
Query
query ExampleDataQuery {
data
}
Response
{
"data": {
"hello": {
"a": 1
},
"someNumbers": [1, 2, 3]
}
}

Overriding built in scalars

To override the behaviour of the built in scalars you can pass a map of overrides to your schema.

Here is a full example of replacing the built in DateTime scalar with one that serializes all datetimes as unix timestamps:

from datetime import datetime, timezone
import strawberry
# Define your custom scalar
EpochDateTime = strawberry.scalar(
datetime,
serialize=lambda value: int(value.timestamp()),
parse_value=lambda value: datetime.fromtimestamp(int(value), timezone.utc),
)
@strawberry.type
class Query:
@strawberry.field
def current_time(self) -> datetime:
return datetime.now()
schema = strawberry.Schema(
Query,
scalar_overrides={
datetime: EpochDateTime,
}
)
result = schema.execute_sync("{ currentTime }")
assert result.data == {"currentTime": 1628683200}

Was this helpful?

Edit on Github

Newsletter 💌

Do you want to receive the latest updates on Strawberry? Subscribe to our newsletter!