> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/pocketbase/pocketbase/llms.txt
> Use this file to discover all available pages before exploring further.

# JSON field

> Store any serialized JSON value with size validation

The json field stores any valid JSON value including objects, arrays, strings, numbers, booleans, and null. It validates JSON syntax and enforces size constraints.

## Configuration options

<ParamField path="maxSize" type="int64" default="1048576">
  Maximum size of the JSON value in bytes (up to 2^53-1). Defaults to 1MB if not set or zero.
</ParamField>

<ParamField path="required" type="bool" default="false">
  When true, requires the field value to be non-empty JSON (not null, empty string, empty array, or empty object).
</ParamField>

## Validation rules

The json field validates:

* **JSON syntax**: Value must be valid JSON
* **Size**: JSON string size must not exceed `maxSize` bytes
* **Required**: If enabled, value cannot be null, `""`, `[]`, or `{}`

## Value normalization

When submitting plain string values (e.g., from multipart/form-data), the following normalization rules apply:

* `"true"` → `true`
* `"false"` → `false`
* `"null"` → `null`
* Numeric strings → JSON numbers
* Valid JSON strings starting with `[`, `{`, or `"` → parsed as JSON
* Other strings → double-quoted JSON strings
* Empty string → `""`

<Info>
  This normalization allows the field to work seamlessly with both JSON and multipart/form-data request formats.
</Info>

## Go examples

<Tabs>
  <Tab title="Basic usage">
    ```go theme={null}
    import "github.com/pocketbase/pocketbase/core"

    field := &core.JSONField{
        Name:     "metadata",
        Required: false,
    }

    collection.Fields.Add(field)

    // Set JSON value
    record.Set("metadata", map[string]any{
        "color": "blue",
        "size":  "large",
        "tags":  []string{"featured", "new"},
    })
    ```
  </Tab>

  <Tab title="With size limit">
    ```go theme={null}
    field := &core.JSONField{
        Name:     "config",
        Required: true,
        MaxSize:  512 * 1024, // 512KB
    }

    collection.Fields.Add(field)

    record.Set("config", map[string]any{
        "theme": "dark",
        "notifications": map[string]bool{
            "email": true,
            "push":  false,
        },
    })
    ```
  </Tab>

  <Tab title="Array values">
    ```go theme={null}
    field := &core.JSONField{
        Name:     "items",
        Required: false,
    }

    collection.Fields.Add(field)

    // Store array
    record.Set("items", []map[string]any{
        {"id": 1, "name": "Item 1"},
        {"id": 2, "name": "Item 2"},
    })
    ```
  </Tab>

  <Tab title="Complex nested data">
    ```go theme={null}
    field := &core.JSONField{
        Name:     "settings",
        Required: true,
        MaxSize:  2 << 20, // 2MB
    }

    collection.Fields.Add(field)

    record.Set("settings", map[string]any{
        "user": map[string]any{
            "preferences": map[string]any{
                "theme":    "dark",
                "language": "en",
            },
            "privacy": map[string]bool{
                "showEmail":   false,
                "showProfile": true,
            },
        },
        "notifications": []string{"email", "push"},
    })
    ```
  </Tab>
</Tabs>

## Database column type

```sql theme={null}
JSON DEFAULT NULL
```

## Working with JSON values

<CodeGroup>
  ```go Setting values theme={null}
  import "github.com/pocketbase/pocketbase/tools/types"

  // From map
  record.Set("data", map[string]any{
      "key": "value",
  })

  // From slice
  record.Set("data", []string{"a", "b", "c"})

  // From JSON string
  jsonStr := `{"name":"John","age":30}`
  record.Set("data", jsonStr)

  // From types.JSONRaw
  raw := types.JSONRaw(`{"key":"value"}`)
  record.Set("data", raw)
  ```

  ```go Getting values theme={null}
  import "encoding/json"

  // Get as types.JSONRaw
  raw := record.Get("data").(types.JSONRaw)

  // Parse into struct
  type MyData struct {
      Name string `json:"name"`
      Age  int    `json:"age"`
  }

  var data MyData
  err := json.Unmarshal([]byte(raw), &data)

  // Parse into map
  var dataMap map[string]any
  err = json.Unmarshal([]byte(raw), &dataMap)
  ```
</CodeGroup>

## Common use cases

<CodeGroup>
  ```go User preferences theme={null}
  field := &core.JSONField{
      Name:    "preferences",
      MaxSize: 10 * 1024, // 10KB
  }

  record.Set("preferences", map[string]any{
      "theme":        "dark",
      "language":     "en",
      "notifications": true,
  })
  ```

  ```go Flexible metadata theme={null}
  field := &core.JSONField{
      Name:    "metadata",
      MaxSize: 50 * 1024, // 50KB
  }

  record.Set("metadata", map[string]any{
      "tags":        []string{"important", "urgent"},
      "source":      "web",
      "customFields": map[string]string{
          "field1": "value1",
          "field2": "value2",
      },
  })
  ```

  ```go API response storage theme={null}
  field := &core.JSONField{
      Name:    "apiResponse",
      MaxSize: 100 * 1024, // 100KB
  }

  record.Set("apiResponse", map[string]any{
      "status":   200,
      "data":     map[string]any{...},
      "headers":  map[string]string{...},
      "timestamp": time.Now().Unix(),
  })
  ```

  ```go Dynamic forms theme={null}
  field := &core.JSONField{
      Name:     "formData",
      Required: true,
  }

  record.Set("formData", map[string]any{
      "firstName": "John",
      "lastName":  "Doe",
      "answers": []map[string]any{
          {"question": "Q1", "answer": "A1"},
          {"question": "Q2", "answer": "A2"},
      },
  })
  ```
</CodeGroup>

## Querying JSON fields

You can query JSON fields using JSONPath-like syntax:

<CodeGroup>
  ```go Simple queries theme={null}
  // Find records where JSON field contains a specific value
  records, err := app.FindRecordsByFilter(
      "items",
      "metadata.category = 'tech'",
      "-created",
      10,
      0,
  )
  ```

  ```go Nested queries theme={null}
  // Query nested JSON properties
  records, err := app.FindRecordsByFilter(
      "users",
      "preferences.theme = 'dark' && preferences.notifications = true",
      "-created",
      10,
      0,
  )
  ```
</CodeGroup>

## Best practices

<Note>
  * Set appropriate `maxSize` to prevent database bloat and performance issues
  * Use structured field types (text, number, etc.) when possible for better queryability
  * JSON fields are great for flexible, schemaless data that varies by record
  * Consider indexing frequently queried JSON properties
  * Validate JSON structure in your application layer for complex schemas
  * Be mindful that JSON fields consume more storage than primitive types
</Note>

## Empty vs null

When `required: true`, these values are considered empty and will fail validation:

* `null`
* `""`
* `[]`
* `{}`

## Zero value

The zero value for json fields is a zero `types.JSONRaw`.
