Repository navigation
Json Mode
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; }
}Sets JSON mode with a schema built from T, sends the request and returns the deserialized object (or null).
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}");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);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.
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>() 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>();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>.
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.
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>();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.");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.
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.
-
Supported types: The schema is built from public properties. Very dynamic types such as
Dictionary<,>orobjectmay not map well to a Gemini schema. -
Null results:
ToObject<T>andGenerateObjectAsync<T>returnnullwhen the response can't be deserialized. Check the result before you use it. - Model compatibility: Check that the model you use supports structured output (JSON mode and response schemas).
Getting Started
- Initialization
- Authentication
- Configuration & Error Handling
- Supported Models
- Migration Guide (v4)
- Release Notes (v4)
Core Features
- Generate Content
- Chat Session
- Streaming
- Multimodal Features
- JSON Mode
- Function Calling
- Embeddings
- Context Caching
Gemini APIs
- Interactions API
- Multimodal Live API
- File Search
- Batch API
- Model Tuning
- Webhooks
- Agent APIs
- Image Generation
- Video Generation
- Speech Generation
- Files Client
- Model Client
Vertex AI
Integrations
Guides
Legacy