Beyond JSON: How TOON Takes the Lead in Spring AI Multi‑Format Responses

This article walks through configuring Spring AI on Spring Boot 3.5.0 to convert tool‑calling results among JSON, TOON, XML, CSV, and YAML, presenting two approaches—per‑tool converters and a global delegator—complete with code samples, limitations, and sample output for each format.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Beyond JSON: How TOON Takes the Lead in Spring AI Multi‑Format Responses

Spring AI tool calling normally returns JSON, but alternative formats such as TOON (Token‑Oriented Object Notation) can improve token efficiency. The article explains how to experiment with these formats in a Spring Boot 3.5.0 application.

1. Tool‑calling workflow

The process consists of defining a tool (name, description, parameter schema), the model invoking the tool, Spring AI executing the tool, serialising the result to JSON, and finally sending the JSON back to the model as part of the conversation history. The ToolCallback interface is the core of this flow.

2. Two interception points

Tool Result level – after tool execution but before JSON serialisation (Method 1).

Response level – after JSON serialisation, converting JSON to another format (Method 2).

2.1 Custom ToolCallResultConverter (Method 1)

Important: This method works only for local tool implementations such as @Tool , FunctionToolCallback , and MethodToolCallback .

A custom converter can delegate to the default JSON converter and then encode the JSON to TOON using the JToon library:

<public static class ToonToolCallResultConverter implements ToolCallResultConverter {
    private ToolCallResultConverter delegate = new DefaultToolCallResultConverter();

    @Override
    public String convert(@Nullable Object result, @Nullable Type returnType) {
        // 1. Convert to JSON with the default converter
        String json = this.delegate.convert(result, returnType);
        // 2. Convert JSON to TOON
        return JToon.encodeJson(json);
    }
}

The converter is registered on a tool via the resultConverter attribute of @Tool:

@Tool(description = "获取泰坦尼克号乘客")
public List<String> randomTitanicToon(@ToolParam(description = "数量") int count) {
    return TitanicData.getTitanicPassengersInRange(30, count);
}

2.2 Global response conversion (Method 2)

For a broader solution, a custom ToolCallbackProvider can wrap the existing provider with a delegator that converts the JSON response to the desired format (TOON, XML, CSV, YAML) for every tool.

public class DelegatorToolCallbackProvider implements ToolCallbackProvider {
    private final ToolCallbackProvider delegate;
    private final ResponseConverter.Format format;

    public DelegatorToolCallbackProvider(ToolCallbackProvider delegate, ResponseConverter.Format format) {
        this.delegate = delegate;
        this.format = format;
    }

    @Override
    public ToolCallback[] getToolCallbacks() {
        return Stream.of(this.delegate.getToolCallbacks())
            .map(cb -> new DelegatorToolCallback(cb, this.format))
            .toArray(ToolCallback[]::new);
    }
}

The ResponseConverter enum defines the supported formats and provides conversion utilities:

public class ResponseConverter {
    public enum Format { TOON, YAML, XML, CSV, JSON }

    public static String convert(String json, Format format) {
        switch (format) {
            case JSON: return json;
            case YAML: return jsonToYaml(toJsonNode(json));
            case XML:  return jsonToXml(toJsonNode(json));
            case CSV:  return jsonToCsv(toJsonNode(json));
            case TOON: return jsonToToon(json);
        }
        throw new IllegalStateException("Unsupported format: " + format);
    }
    // conversion helpers omitted for brevity
}

3. Test runner

A CommandLineRunner demonstrates the end‑to‑end flow, prompting the model for Titanic passenger data and printing the formatted response and token usage.

@Component
public class ToolReturnFormatRunner implements CommandLineRunner {
    private final ChatClient chatClient;
    private final DelegatorToolCallbackProvider provider;

    public ToolReturnFormatRunner(ChatClient.Builder builder, ToolCallbackProvider original, @Value("${spring.ai.tool.response.format:JSON}") String fmt) {
        this.provider = new DelegatorToolCallbackProvider(original, ResponseConverter.Format.valueOf(fmt));
        this.chatClient = builder.defaultTools(provider).build();
    }

    @Override
    public void run(String... args) throws Exception {
        var response = chatClient.prompt("显示5个乘客信息").call().chatResponse();
        System.out.println(String.format("RESPONSE: %s
USAGE: %s", response.getResult().getOutput().getText(), response.getMetadata().getUsage()));
    }
}

4. Sample outputs

Running the application with ResponseConverter.Format.TOON yields the following representations (images omitted for brevity):

JSON output

CSV output

TOON output

XML output

YAML output

Token usage statistics are also displayed, showing the impact of each format.

5. Limitations

Incompatible with @McpTool (Model Context Protocol tools).

Each tool that needs a custom format requires its own converter implementation.

Maintenance overhead increases when tool definitions change.

Overall, the guide provides a concrete, step‑by‑step method for extending Spring AI tool responses beyond JSON, allowing developers to evaluate the trade‑offs of alternative serialisation formats such as TOON.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

backendJavaSpring BootSpring AITool Callingresponse-formattoon
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.