◉GEMINI LABJP
●TTS — The three TTS preview models shut down on 12/18 per the deprecations page, not 11/17●CLI 0.68 — Gemini CLI stable is v0.68.0, with v0.69.0-preview.0 (11/10) on the preview channel●GEMINI 2.5 — gemini-2.5-pro and 2.5-flash shut down on the API on 12/1, 16 days left. Move to 3.8 Flash or 3.5 Flash-Lite●NODE 26 — On Node 26, Gemini CLI's timeout settings reportedly stop applying to model requests●OMNI 1.1 — From 12/3, requests to gemini-omni-1.1-flash are routed to 1.2 Flash automatically●NEW — Getting Consistent JSON Through the OpenAI-Compatible Layer, in Three Steps●TTS — The three TTS preview models shut down on 12/18 per the deprecations page, not 11/17●CLI 0.68 — Gemini CLI stable is v0.68.0, with v0.69.0-preview.0 (11/10) on the preview channel●GEMINI 2.5 — gemini-2.5-pro and 2.5-flash shut down on the API on 12/1, 16 days left. Move to 3.8 Flash or 3.5 Flash-Lite●NODE 26 — On Node 26, Gemini CLI's timeout settings reportedly stop applying to model requests●OMNI 1.1 — From 12/3, requests to gemini-omni-1.1-flash are routed to 1.2 Flash automatically●NEW — Getting Consistent JSON Through the OpenAI-Compatible Layer, in Three Steps
Articles/API / SDK
◈ API / SDK/2026-06-27Advanced

Your Gemini Structured Output Keys Keep Reordering — Pin Them With propertyOrdering

You constrained the shape with responseSchema, yet the JSON key order shifts between calls and your snapshot tests go red for no reason. Here is why field order is not guaranteed by default, how propertyOrdering fixes it, how Pydantic sets it for you, and how to align few-shot examples — all with working code.

Gemini API256Structured Output12propertyOrderingSnapshot TestingJSON Schema

✦ Premium Article

When you automate content operations across several sites, you end up asking Gemini for structured metadata constantly: give me the title, category, tags, and summary as JSON, then push that straight into the next stage. I felt safe because responseSchema constrained the shape. Then one day my snapshot tests started going red with no explanation.

Opening the diff was almost anticlimactic. The values were identical. The only thing that had changed was the order of the keys. An output that was {"title": ..., "tags": ...} came back the next run as {"tags": ..., "title": ...}. Right types, right values, and yet a text comparison reports a mismatch.

This article walks through that behavior — structured output does not guarantee field order by default — and how propertyOrdering pins it, including the trap that bites you once you add few-shot examples. It follows the same order in which I actually hit each issue as an indie developer maintaining pipelines across my own Dolice Labs sites.

Why the order moves — JSON schema being honest

The root of the confusion is in JSON itself: object keys carry no notion of order. The Schema object's properties (it descends from OpenAPI) is conceptually an unordered map, and the order the model writes fields in is decided at generation time. Even with temperature at 0 and a byte-identical prompt, sampling noise can swap the arrangement.

Google's structured output guidance says as much: if you depend on order, specify it explicitly. So there are two separate guarantees here — the type can be fixed, but the ordering has to be fixed separately. Miss that distinction and you lose time on the assumption that "I constrained the type, so the output must be fully determined," which is exactly the hole I fell into.

Here is the typical code that hands Gemini a raw dict schema.

# pip install google-genai
from google import genai
from google.genai import types
 
client = genai.Client(api_key="YOUR_GEMINI_API_KEY")
 
# A dict schema with no ordering specified
schema = {
    "type": "object",
    "properties": {
        "title": {"type": "string"},
        "category": {"type": "string"},
        "tags": {"type": "array", "items": {"type": "string"}},
        "summary": {"type": "string"},
    },
    "required": ["title", "category", "tags", "summary"],
}
 
resp = client.models.generate_content(
    model="gemini-2.5-flash",
    contents="Extract the metadata for this article: ...",
    config=types.GenerateContentConfig(
        response_mime_type="application/json",
        response_schema=schema,
    ),
)
print(resp.text)
# Sometimes {"title":..., "category":..., "tags":[...], "summary":...}
# Other times {"summary":..., "title":..., "tags":[...], "category":...}

Even though response_schema is set, the raw key order of resp.text wobbles between calls. If you only json.loads it and read values, nothing is wrong. The trouble appears only when you save and compare the generated JSON text itself. For me that was snapshot tests, plus a workflow that committed generated results to git as diffs.

Pin the order with propertyOrdering

The fix is simple: add propertyOrdering (camelCase in REST/JSON) to the Schema and list the property names in the order you want them emitted.

schema = {
    "type": "object",
    "properties": {
        "title": {"type": "string"},
        "category": {"type": "string"},
        "tags": {"type": "array", "items": {"type": "string"}},
        "summary": {"type": "string"},
    },
    # Add just this. The output stabilizes in this order.
    "propertyOrdering": ["title", "category", "tags", "summary"],
    "required": ["title", "category", "tags", "summary"],
}
 
resp = client.models.generate_content(
    model="gemini-2.5-flash",
    contents="Extract the metadata for this article: ...",
    config=types.GenerateContentConfig(
        response_mime_type="application/json",
        response_schema=schema,
    ),
)
# Output is always title -> category -> tags -> summary

propertyOrdering is an ordering hint, not a type constraint. Because validation still passes without it, it is easy to forget when you hand-write dict schemas — that has been my lived experience. If you have nested objects, each child Schema needs its own propertyOrdering too. Write it only at the top and the nested fields keep shuffling, and the diffs come back.

✦

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
✦Understand why responseSchema does not pin key order, and add one line of propertyOrdering to a dict schema to lock it down today
✦Learn how passing a Pydantic model as response_schema turns declaration order into propertyOrdering automatically, with verification code
✦Stop snapshot regressions that flapped purely on key order, using a two-layer fix: pin the order and normalize on compare
Secure payment via Stripe · Cancel anytime
✦

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Gemini Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

Related Articles

◈ API / SDK2026-11-14
When JSON Shapes Drift Through Gemini's OpenAI Compatibility Layer: Three Steps to response_json_schema Without Rewriting Callers
If your OpenAI SDK code points at Gemini and structured output seems ignored, here is how to check whether a schema is actually sent, and how to move to the Gemini SDK's response_json_schema while keeping the same function boundary.
◈ API / SDK2026-06-12
Building an App Store Rejection Workflow with the Gemini API — From Structured Notices to Resolution Center Replies
How I use the Gemini API to parse App Store rejection notices into structured JSON, cross-check guidelines, draft Resolution Center replies, and run pre-submission checks as an indie developer.
◈ API / SDK2026-05-21
When responseSchema enum returns unexpected values — debugging Gemini API
Why Gemini API sometimes returns values outside the enum in responseSchema, with a script to measure the leak rate on your own data and three layered fixes: prompt definitions, one capped retry, and an SDK version check.