Pydantic V2 Field Validator Equivalent to Values Argument: Accessing Other Fields

In Pydantic V2, the values argument from V1's @validator is replaced by the info.data attribute of the ValidationInfo object passed to @field_validator methods.

When migrating FastAPI applications from Pydantic V1 to V2, developers must update their validation logic to accommodate the removal of the values parameter. The fastapi/fastapi repository implements this transition through the ValidationInfo pattern, providing equivalent functionality for cross-field validation while maintaining type safety and performance.

Understanding the Migration from values to info.data

In Pydantic V1, the @validator decorator exposed a values dictionary containing already-validated field values:

@validator("age")
def check_age(cls, v, values):
    if v < values.get("birth_year", 0):
        raise ValueError("age must be greater than birth_year")

Pydantic V2 eliminates the values parameter entirely. The new @field_validator decorator instead supplies a ValidationInfo object (conventionally named info) as the second parameter. This object contains an attribute info.data, which is a dictionary mapping field names to their validated values.

The ValidationInfo Object Structure

The ValidationInfo object exposes info.data, a dictionary containing values that have been validated up to that point. When using mode="after", this dictionary contains the complete model state after field assignment. FastAPI's compatibility layer forwards this information through fastapi._compat.v2.with_info_plain_validator_function, ensuring consistent behavior across Pydantic versions.

Implementing Cross-Field Validation in Pydantic V2

To validate one field against another using the Pydantic V2 equivalent of the values argument, import ValidationInfo and access info.data within your validator:

from pydantic import BaseModel, ValidationInfo, field_validator

class Item(BaseModel):
    price: float
    discount: float

    @field_validator("discount", mode="after")
    @classmethod
    def discount_must_be_less_than_price(
        cls, v: float, info: ValidationInfo
    ) -> float:
        # `info.data` holds the already-validated fields, i.e. {"price": …, "discount": …}

        if v > info.data["price"]:
            raise ValueError("discount cannot exceed price")
        return v

In this example, info.data["price"] provides the same functionality as the deprecated values["price"] from Pydantic V1.

Using FastAPI's Compatibility Wrapper

FastAPI maintains internal compatibility through utilities defined in fastapi/_compat/v2.py. The with_info_plain_validator_function decorator ensures ValidationInfo propagates correctly through FastAPI's validation pipeline:

from fastapi import FastAPI
from fastapi._compat.v2 import with_info_plain_validator_function
from pydantic import BaseModel, ValidationInfo, field_validator

class User(BaseModel):
    username: str
    password: str

    @field_validator("password", mode="before")
    @classmethod
    @with_info_plain_validator_function
    def hash_password(cls, v: str, info: ValidationInfo) -> str:
        # `info.data` contains {"username": …, "password": …}

        return hash_function(v)          # replace with real hashing

This pattern appears throughout FastAPI's codebase, including in fastapi/openapi/models.py, demonstrating how the framework handles Pydantic V2 validation internally.

Using model_validator for Complex Scenarios

For validations requiring simultaneous access to multiple fields, Pydantic V2 introduces @model_validator. While @field_validator operates on individual fields, @model_validator receives the complete model state:

from pydantic import BaseModel, ValidationInfo, model_validator

class Config(BaseModel):
    host: str
    port: int

    @model_validator(mode="after")
    @classmethod
    def check_host_and_port(cls, info: ValidationInfo) -> "Config":
        data = info.data
        if data["host"] == "localhost" and data["port"] != 8000:
            raise ValueError("localhost must use port 8000")
        return cls(**data)

Before vs After Validation Modes

  • mode="before": Runs validation on raw input before Pydantic performs type coercion. The info.data dictionary contains pre-validation values.
  • mode="after": Runs validation after field assignment and type coercion. The info.data dictionary contains transformed Python objects.

How FastAPI Handles the Compatibility Layer

The transition from values to info.data is managed internally by FastAPI through specific compatibility utilities. The file fastapi/_compat/v2.py defines with_info_plain_validator_function, which wraps validator functions to inject ValidationInfo objects correctly.

Test implementations in tests/test_filter_pydantic_sub_model_pv2.py demonstrate practical applications of field_validator with info.data, providing reference implementations for complex validation scenarios. These tests verify that FastAPI models correctly pass field context through the Pydantic V2 validation pipeline.

Summary

  • Pydantic V2 replaces the values argument with info.data from the ValidationInfo object in @field_validator methods.
  • Import ValidationInfo from pydantic and accept it as the second parameter in validator functions to access other fields.
  • FastAPI provides with_info_plain_validator_function in fastapi/_compat/v2.py for framework-specific validation wrapping.
  • Use @model_validator when validation logic spans multiple fields simultaneously.
  • Reference implementations exist in tests/test_filter_pydantic_sub_model_pv2.py and fastapi/openapi/models.py.

Frequently Asked Questions

What replaced the values argument in Pydantic V2?

The values dictionary from Pydantic V1's @validator has been replaced by info.data in Pydantic V2's @field_validator. The ValidationInfo object, passed as the second argument to validator functions, contains the data attribute which provides access to other validated fields during the validation process.

How do I import ValidationInfo in Pydantic V2?

Import ValidationInfo directly from the pydantic module: from pydantic import ValidationInfo. Pass it as a parameter to your @field_validator decorated method alongside the field value being validated. The object is automatically populated by Pydantic's validation engine.

What is the difference between mode="before" and mode="after" in field_validator?

mode="before" runs validation on raw input data before Pydantic performs type coercion, allowing you to transform or validate the original input values. mode="after" runs validation after the field has been converted to its declared Python type. When accessing info.data, "after" mode provides already-transformed values, whereas "before" mode may contain raw, uncoerced input.

Does FastAPI require special handling for Pydantic V2 validators?

FastAPI automatically handles Pydantic V2 validators through its internal compatibility layer defined in fastapi/_compat/v2.py. The with_info_plain_validator_function decorator ensures ValidationInfo objects propagate correctly through FastAPI's dependency injection and validation systems, maintaining compatibility with both Pydantic V1 and V2.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →