Structured Output

Force the model to produce valid JSON conforming to a schema. Both APIs support this.

Chat Completions

Use ResponseFormat to control the output format:

Free-Form JSON

using UniLM
using JSON

chat = Chat(
    model="gpt-5.2",
    response_format=ResponseFormat()  # type="json_object"
)
push!(chat, Message(Val(:system), "You output JSON. Always respond with valid JSON."))
push!(chat, Message(Val(:user), "List 3 programming languages with their year of creation."))
println("Response format type: ", chat.response_format.type)
println("Request body:")
println(JSON.json(chat))
Response format type: json_object
Request body:
{"response_format":{"type":"json_object"},"messages":[{"role":"system","content":"You output JSON. Always respond with valid JSON."},{"role":"user","content":"List 3 programming languages with their year of creation."}],"model":"gpt-5.2"}
result = chatrequest!(chat)
if result isa LLMSuccess
    println(JSON.json(JSON.parse(result.message.content), 2))
else
    println("Request failed — see result for details")
end
{
  "languages": [
    {
      "name": "C",
      "year_of_creation": 1972
    },
    {
      "name": "Python",
      "year_of_creation": 1991
    },
    {
      "name": "Java",
      "year_of_creation": 1995
    }
  ]
}

JSON Schema (Strict)

schema = ResponseFormat(UniLM.JsonSchemaAPI(
    name="languages",
    description="A list of programming languages",
    schema=Dict(
        "type" => "object",
        "properties" => Dict(
            "languages" => Dict(
                "type" => "array",
                "items" => Dict(
                    "type" => "object",
                    "properties" => Dict(
                        "name" => Dict("type" => "string"),
                        "year" => Dict("type" => "integer")
                    ),
                    "required" => ["name", "year"]
                )
            )
        ),
        "required" => ["languages"]
    )
))

chat = Chat(model="gpt-5.2", response_format=schema)
push!(chat, Message(Val(:system), "Return structured data about programming languages."))
push!(chat, Message(Val(:user), "List Julia, Python, and Rust"))
println("Schema name: ", schema.json_schema.name)
println("Response format type: ", schema.type)
Schema name: languages
Response format type: json_schema
result = chatrequest!(chat)
if result isa LLMSuccess
    println(JSON.json(JSON.parse(result.message.content), 2))
else
    println("Request failed — see result for details")
end
{
  "languages": [
    {
      "name": "Julia",
      "year": 2012
    },
    {
      "name": "Python",
      "year": 1991
    },
    {
      "name": "Rust",
      "year": 2010
    }
  ]
}

Responses API

The Responses API uses TextConfig with convenience constructors:

JSON Object

result = respond("List 3 colors as a JSON object", text=json_object_format())
if result isa ResponseSuccess
    println(output_text(result))
else
    println("Request failed — ", output_text(result))
end
{
  "colors": ["red", "green", "blue"]
}

JSON Schema

fmt = json_schema_format(
    "colors",
    "A structured list of colors",
    Dict(
        "type" => "object",
        "properties" => Dict(
            "colors" => Dict(
                "type" => "array",
                "items" => Dict(
                    "type" => "object",
                    "properties" => Dict(
                        "name" => Dict("type" => "string"),
                        "hex" => Dict("type" => "string")
                    ),
                    "required" => ["name", "hex"],
                    "additionalProperties" => false
                )
            )
        ),
        "required" => ["colors"],
        "additionalProperties" => false
    ),
    strict=true
)
println("Format type: ", fmt.format.type)
println("Schema strict: ", fmt.format.strict)
Format type: json_schema
Schema strict: true
result = respond("List red, green, and blue with their hex codes", text=fmt)
if result isa ResponseSuccess
    println(JSON.json(JSON.parse(output_text(result)), 2))
else
    println("Request failed — ", output_text(result))
end
{
  "colors": [
    {
      "name": "Red",
      "hex": "#FF0000"
    },
    {
      "name": "Green",
      "hex": "#00FF00"
    },
    {
      "name": "Blue",
      "hex": "#0000FF"
    }
  ]
}

Plain Text Format

tc = text_format()
println("Default format type: ", tc.format.type)
Default format type: text

Convenience Constructors

ConstructorFormat
json_object_format()Unstructured JSON
json_schema_format(name, desc, schema)Schema-constrained JSON
text_format()Plain text (default)

See Also