Jump to content

Connect Leeroopedia MCP: Equip your AI agents to search best practices, build plans, verify code, diagnose failures, and look up hyperparameter defaults.

Implementation:Bentoml BentoML IO Descriptor JSON

From Leeroopedia
Knowledge Sources
Domains IO Descriptors, JSON Serialization, API Specification
Last Updated 2026-02-13 15:00 GMT

Overview

The JSON IO descriptor defines API specification for BentoML services that accept or return JSON data, with optional Pydantic model validation and a custom JSON encoder supporting NumPy, Pandas, dataclasses, and attrs objects.

Description

The JSON class is an IO descriptor that handles JSON-based inputs and outputs for BentoML services. It extends IODescriptor[JSONType] where JSONType is a union of str, Dict[str, Any], pydantic.BaseModel, and None. Key features include:

  • Pydantic model integration: When a pydantic_model is provided, incoming JSON is validated and parsed into the specified Pydantic model instance. Supports both Pydantic v1 (parse_obj) and Pydantic v2 (model_validate).
  • Custom JSON encoder: The DefaultJsonEncoder class extends json.JSONEncoder to handle serialization of numpy.ndarray, numpy.generic, pandas.DataFrame, pandas.Series, pydantic.BaseModel, dataclasses, and attrs-decorated classes.
  • OpenAPI schema generation: Generates schemas from Pydantic models for API documentation, handling both Pydantic v1 (model_process_schema) and v2 (model_json_schema) schema generation APIs. Produces component schemas for nested Pydantic models.
  • HTTP request/response handling: Parses JSON from request bodies, applies Pydantic validation if configured, and serializes responses with the configured JSON encoder.
  • gRPC protobuf serialization: Converts between google.protobuf.struct_pb2.Value messages and JSON types using ParseDict and MessageToDict. The helper function parse_dict_to_proto handles conversion of both standard types and custom objects via the JSON encoder.
  • Pydantic version compatibility: Explicitly checks pkg_version_info("pydantic") to branch between v1 and v2 APIs throughout the codebase.

Usage

Use this descriptor when building BentoML services that accept structured JSON input, especially when you want schema validation through Pydantic models. It is specified as the input or output parameter in the @svc.api decorator.

Code Reference

Source Location

Signature

class JSON(
    IODescriptor[JSONType],
    descriptor_id="bentoml.io.JSON",
    proto_fields=("json",),
):
    def __init__(
        self,
        *,
        pydantic_model: type[pydantic.BaseModel] | None = None,
        validate_json: bool | None = None,
        json_encoder: type[json.JSONEncoder] = DefaultJsonEncoder,
    ): ...

    def _from_sample(self, sample: JSONType) -> JSONType: ...
    def to_spec(self) -> dict[str, t.Any]: ...
    @classmethod
    def from_spec(cls, spec: dict[str, t.Any]) -> Self: ...
    def input_type(self) -> UnionType: ...
    def openapi_schema(self) -> Schema: ...
    def openapi_components(self) -> dict[str, t.Any] | None: ...
    def openapi_example(self): ...
    def openapi_request_body(self) -> dict[str, t.Any]: ...
    def openapi_responses(self) -> OpenAPIResponse: ...
    async def from_http_request(self, request: Request) -> JSONType: ...
    async def to_http_response(self, obj: JSONType | pydantic.BaseModel, ctx: Context | None = None): ...
    async def from_proto(self, field: struct_pb2.Value | bytes) -> JSONType: ...
    async def to_proto(self, obj: JSONType) -> struct_pb2.Value: ...


class DefaultJsonEncoder(json.JSONEncoder):
    def default(self, o: type) -> t.Any: ...


def parse_dict_to_proto(
    obj: JSONType,
    msg: _message.Message,
    json_encoder: type[json.JSONEncoder] = DefaultJsonEncoder,
) -> t.Any: ...

Import

from bentoml.io import JSON

I/O Contract

Inputs

Name Type Required Description
pydantic_model type[pydantic.BaseModel] or None No Pydantic model class for input validation and schema generation. When set, incoming JSON is parsed into an instance of this model.
validate_json bool or None No Deprecated option. A warning is logged if provided.
json_encoder type[json.JSONEncoder] No Custom JSON encoder class. Defaults to DefaultJsonEncoder which handles numpy, pandas, dataclass, and attrs objects.

Outputs

Name Type Description
JSONType str, Dict[str, Any], pydantic.BaseModel, or None The deserialized JSON object from an incoming request, or the object to serialize for a response.

Usage Examples

from __future__ import annotations

import bentoml
from bentoml.io import JSON, NumpyNdarray
from pydantic import BaseModel
import pandas as pd
from typing import Optional, Any

class IrisFeatures(BaseModel):
    sepal_len: float
    sepal_width: float
    petal_len: float
    petal_width: float
    request_id: Optional[int] = None

    class Config:
        extra = "forbid"

runner = bentoml.sklearn.get("iris_clf_with_feature_names:latest").to_runner()
svc = bentoml.legacy.Service("iris_classifier_pydantic", runners=[runner])

input_spec = JSON(pydantic_model=IrisFeatures)

@svc.api(input=input_spec, output=NumpyNdarray())
def classify(input_data: IrisFeatures) -> Any:
    input_df = pd.DataFrame([input_data.dict(exclude={"request_id"})])
    return runner.run(input_df)


# Using from_sample with a plain dictionary
input_spec2 = JSON.from_sample({"hello": "world", "foo": "bar"})

@svc.api(input=input_spec2, output=JSON())
async def echo(input_data: dict[str, Any]) -> dict[str, Any]:
    return input_data

Related Pages

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment