Skip to content

Json Mode

Gunpal Jain edited this page Nov 15, 2026 · 4 revisions

JSON mode makes Gemini return structured JSON that matches a C# type. The SDK builds the response schema from your class, sends it with the request and deserializes the reply. It can also return enum values or pull JSON blocks out of free-form text.

Package: Google_GenerativeAI. Setup: Initialization.

using GenerativeAI;
using GenerativeAI.Types;

var model = new GoogleAi("YOUR_API_KEY").CreateGenerativeModel(GoogleAIModels.Gemini38Flash);

public class SampleJsonClass
{
    public string? Name { get; set; }
    public int Age { get; set; }
}

1. Automatic JSON Handling

GenerateObjectAsync<T>

Sets JSON mode with a schema built from T, sends the request and returns the deserialized object (or null).

With a text prompt

var person = await model.GenerateObjectAsync<SampleJsonClass>("Give me a JSON object representing a person.");
if (person != null)
    Console.WriteLine($"Name: {person.Name}, Age: {person.Age}");

With a list of Part objects

Use parts to mix text with images or other media:

var parts = new List<Part> { new Part { Text = "Give me a JSON object representing a person." } };
var person = await model.GenerateObjectAsync<SampleJsonClass>(parts);

With a full request

var request = new GenerateContentRequest();
request.AddText("Give me a JSON object representing a person.");

var person = await model.GenerateObjectAsync<SampleJsonClass>(request);

To build the request from a Content object, add it with request.AddContent(content) and then call the request overload.

GenerateContentAsync<T> and ToObject<T>

Use this form when you also need the full GenerateContentResponse, for example for usage metadata or finish reasons:

var request = new GenerateContentRequest();
request.AddText("Give me a JSON object representing a person.");

GenerateContentResponse response = await model.GenerateContentAsync<SampleJsonClass>(request);
var person = response.ToObject<SampleJsonClass>();

UseJsonMode<T> on the request

UseJsonMode<T>() sets ResponseMimeType = "application/json" and a ResponseSchema generated from T. Use it with the regular GenerateContentAsync:

var request = new GenerateContentRequest();
request.UseJsonMode<SampleJsonClass>();
request.AddText("Give me a JSON object representing a person.");

var response = await model.GenerateContentAsync(request);
var person = response.ToObject<SampleJsonClass>();

Lists of objects

For an array response, use List<T> as the type argument:

List<SampleJsonClass>? people =
    await model.GenerateObjectAsync<List<SampleJsonClass>>("Give me three people as JSON.");

When a free-text response contains several separate JSON objects, response.ToObjects<T>() deserializes each block that matches T and returns them as a List<T>.

Model-level JSON mode

Set model.UseJsonMode = true to make the model return JSON for every request. JSON mode can't be combined with Google Search, code execution or legacy grounding. Combining them throws NotSupportedException.

2. Enum Mode

GenerateEnumAsync<T> (or request.UseEnumMode<T>()) uses the text/x.enum MIME type, which limits the answer to one value of the enum:

public enum Sentiment { Positive, Neutral, Negative }

var sentiment = await model.GenerateEnumAsync<Sentiment>("Classify: 'I love this product!'");
Console.WriteLine(sentiment);

// Or manually
var request = new GenerateContentRequest();
request.UseEnumMode<Sentiment>();
request.AddText("Classify: 'The service was slow.'");
var response = await model.GenerateContentAsync(request);
var value = response.ToEnum<Sentiment>();

3. Manual Schema and JSON Parsing

Setting the schema yourself

GenerationConfig.ResponseSchema takes a Schema (OpenAPI subset). GoogleSchemaHelper.ConvertToSchema<T>() builds one from a type. ResponseJsonSchema takes a raw JSON Schema as a JsonNode.

var request = new GenerateContentRequest();
request.GenerationConfig = new GenerationConfig
{
    ResponseMimeType = "application/json",
    ResponseSchema = GoogleSchemaHelper.ConvertToSchema<SampleJsonClass>()
};
request.AddText("Give me a really good response.");

Extracting JSON blocks from text

Without JSON mode, models often wrap JSON in Markdown code fences. ExtractJsonBlocks() finds those blocks, and JsonBlock.ToObject<T>() deserializes each one:

var request = new GenerateContentRequest();
request.AddText("Give me some JSON describing two people.");

var response = await model.GenerateContentAsync(request);
var jsonBlocks = response.ExtractJsonBlocks();
var myObjects = jsonBlocks.Select(block => block.ToObject<SampleJsonClass>());

foreach (var obj in myObjects)
{
    if (obj != null)
        Console.WriteLine($"Name: {obj.Name}, Age: {obj.Age}");
}

ExtractJsonBlocks() and ToObject<T>() are also available on Content, and ExtractJsonBlocks() on plain string.

Serializer Options and NativeAOT

model.GenerateObjectJsonSerializerOptions controls how schemas are built and responses are deserialized. With NativeAOT or trimming, where reflection is disabled, pass options that include a source-generated JsonSerializerContext for your types:

model.GenerateObjectJsonSerializerOptions = new JsonSerializerOptions
{
    TypeInfoResolver = MyJsonContext.Default
};

// Extension methods also accept options
var person = response.ToObject<SampleJsonClass>(MyJsonContext.Default.Options);

See NativeAOT and Trimming Guidelines.

Important Considerations

  1. Supported types: The schema is built from public properties. Very dynamic types such as Dictionary<,> or object may not map well to a Gemini schema.
  2. Null results: ToObject<T> and GenerateObjectAsync<T> return null when the response can't be deserialized. Check the result before you use it.
  3. Model compatibility: Check that the model you use supports structured output (JSON mode and response schemas).

Related Pages

API Reference

Clone this wiki locally