📌 内容摘要
- Claude 默认使用 Markdown 格式输出,但在 API 环境或纯文本场景中这往往是问题而非优势。
- 本文覆盖4种输出格式的完整控制方法:Markdown、JSON、XML、纯文本,附每种格式的 Prompt 模板。
- 重点解决开发者最常遇到的问题:如何获得稳定可解析的 JSON、如何防止 Claude 在不该用 Markdown 的地方乱用。
- 文末提供完整的格式解析和容错代码,处理 Claude 输出格式不规范的边界情况。
一、Claude 的默认格式行为
了解 Claude 的默认行为,是控制输出格式的第一步。
Claude 在判断输出格式时,会根据对话上下文做出推断:在 claude.ai 网页端,它倾向于使用 Markdown(因为界面会渲染);通过 API 调用时,它的格式行为相对中性。但无论哪种环境,Claude 对明确的格式指令响应非常好——你告诉它用什么格式,它就用什么格式。
| 场景 | Claude 默认行为 | 推荐做法 |
|---|---|---|
| claude.ai 网页对话 | 倾向使用 Markdown | 通常不需要干预,Markdown 会被正常渲染 |
| API 调用(展示给用户) | 可能带 Markdown 标记 | 明确指定格式,或在前端渲染 Markdown |
| API 调用(程序解析) | Markdown 标记会干扰解析 | 强制要求 JSON 或纯文本 |
| 批量数据处理 | 格式可能不一致 | 严格约束输出格式,加容错解析 |
二、Markdown 格式控制
2.1 开启/增强 Markdown(适合文档和报告)
请用 Markdown 格式撰写以下报告,要求: - 用 ## 作为主标题,### 作为子标题 - 重要数字和关键词用 **粗体** 标注 - 对比数据用表格呈现 - 操作步骤用有序列表 - 注意事项用无序列表 - 代码示例用代码块包裹 报告主题:[主题]
2.2 禁用 Markdown(适合 API 程序处理或纯文本场景)
# System Prompt(推荐方式,在 API 中设置) 你的输出将被程序直接处理,请严格遵守: - 不使用任何 Markdown 格式(不用 **、##、`、- 等符号) - 不使用 emoji - 使用纯文本输出 - 段落之间用换行符分隔 --- # 对话中临时禁用(次优方式) 请用纯文本回答,不要使用任何 Markdown 格式符号。
2.3 精确控制 Markdown 使用范围
格式规则: - ✅ 允许使用:代码块(```)、行内代码(`)、表格 - ✅ 允许使用:有序/无序列表 - ❌ 禁止使用:标题(#、##、###) - ❌ 禁止使用:粗体(**)和斜体(*) - ❌ 禁止使用:分隔线(---) 理由:输出会显示在不支持标题渲染的环境中,但代码需要高亮显示。
三、JSON 格式输出(开发者最常用)
JSON 是 API 开发中最常需要的输出格式,也是最容易出问题的格式——Claude 有时会在 JSON 前后加解释文字,或者用 Markdown 代码块包裹。以下是确保获得纯净 JSON 的完整方案。
3.1 基础 JSON 输出
分析以下产品评论,以 JSON 格式返回结果。
严格要求:
- 只输出 JSON,不要任何前缀说明或后缀总结
- 不要用 Markdown 代码块(不要 ```json``` 包裹)
- 严格遵守以下 schema,不增减任何字段
JSON schema:
{
"sentiment": "positive | negative | neutral | mixed",
"score": -1.0 到 1.0 的浮点数(-1最负面,1最正面),
"key_issues": ["问题1", "问题2"],
"key_praises": ["优点1", "优点2"],
"recommended_action": "reply | escalate | ignore"
}
评论内容:[粘贴评论]
3.2 复杂嵌套 JSON
从以下职位描述中提取结构化信息,只输出 JSON,不要其他内容:
{
"job_title": "职位名称",
"company": "公司名称",
"location": {
"city": "城市",
"is_remote": true 或 false
},
"salary": {
"min": 最低薪资数字(元/月,没有则 null),
"max": 最高薪资数字(元/月,没有则 null),
"currency": "CNY"
},
"requirements": {
"years_of_experience": 最低年限数字,
"education": "学历要求",
"skills": ["技能1", "技能2"]
},
"job_type": "full-time | part-time | contract | internship",
"posted_date": "YYYY-MM-DD 格式,无法确定则 null"
}
职位描述:[粘贴 JD]
3.3 JSON 数组批量处理
对以下 5 条评论逐一分析,返回 JSON 数组。
只输出 JSON 数组,格式:
[
{"id": 1, "sentiment": "positive|negative|neutral", "score": 数字},
{"id": 2, ...},
...
]
评论列表:
1. 物流很快,商品完好,好评!
2. 假货,和描述完全不符,差评。
3. 还可以,价格偏贵。
4. 包装很精致,送礼不错。
5. 质量一般,但客服态度好。
3.4 Python 健壮解析代码
import anthropic
import json
import re
from typing import Any, Optional
client = anthropic.Anthropic()
def extract_json(text: str) -> Optional[Any]:
"""
从 Claude 输出中提取 JSON,处理各种不规范情况:
1. 纯 JSON
2. ```json ... ``` 代码块包裹
3. JSON 前后有多余文字
4. 单引号替代双引号(非标准但有时出现)
"""
text = text.strip()
# 情况1:尝试直接解析
try:
return json.loads(text)
except json.JSONDecodeError:
pass
# 情况2:提取代码块中的 JSON
code_block = re.search(r'```(?:json)?\s*([\s\S]*?)\s*```', text)
if code_block:
try:
return json.loads(code_block.group(1))
except json.JSONDecodeError:
pass
# 情况3:提取第一个完整的 JSON 对象或数组
json_pattern = re.search(r'(\{[\s\S]*\}|\[[\s\S]*\])', text)
if json_pattern:
try:
return json.loads(json_pattern.group(1))
except json.JSONDecodeError:
pass
# 情况4:修复单引号并重试
fixed = text.replace("'", '"')
try:
return json.loads(fixed)
except json.JSONDecodeError:
pass
return None # 所有尝试失败
def call_with_json_output(
prompt: str,
schema_description: str,
system: str = "",
max_retries: int = 3,
) -> Optional[Any]:
"""
调用 Claude 并确保获得有效 JSON
失败时自动重试,最多 max_retries 次
"""
system_prompt = f"""{system}
你的输出将被程序直接解析,必须严格遵守:
1. 只输出 JSON,不要任何解释文字
2. 不要使用 Markdown 代码块包裹
3. 确保输出是合法的 JSON 格式""".strip()
full_prompt = f"""{prompt}
输出 JSON schema:
{schema_description}
记住:只输出 JSON,没有其他任何内容。"""
for attempt in range(max_retries):
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=2048,
system=system_prompt,
messages=[{"role": "user", "content": full_prompt}]
)
result = extract_json(response.content[0].text)
if result is not None:
return result
print(f"第{attempt+1}次尝试解析失败,原始输出:{response.content[0].text[:100]}...")
# 重试时加强格式要求
full_prompt += "\n\n⚠️ 上次输出格式不正确,请只输出纯 JSON,不要任何其他内容。"
return None
# 使用示例
result = call_with_json_output(
prompt="分析评论:'产品不错,但发货太慢了,等了5天'",
schema_description='{"sentiment": "string", "score": "number -1 to 1", "issues": ["string"]}'
)
print(result) # {'sentiment': 'mixed', 'score': 0.1, 'issues': ['发货速度慢']}
四、XML 格式输出
Claude 对 XML 标签有特别好的响应性——Anthropic 官方文档明确推荐使用 XML 标签来结构化复杂 Prompt 和输出。XML 适合需要清晰层次结构、或者需要同时包含多种类型内容的场景。
4.1 基础 XML 输出
分析以下代码,以 XML 格式返回审查结果:
<code_review>
<summary>整体评价(一句话)</summary>
<score>0-100的整数</score>
<issues>
<issue severity="critical|high|medium|low">
<location>行号或函数名</location>
<description>问题描述</description>
<fix>修复建议</fix>
</issue>
(可能有多个 issue 标签)
</issues>
<approved>true 或 false</approved>
</code_review>
代码:[粘贴代码]
4.2 XML 解析代码
import xml.etree.ElementTree as ET
import re
from typing import Optional
def extract_xml(text: str, root_tag: str) -> Optional[ET.Element]:
"""
从 Claude 输出中提取并解析 XML
root_tag: 根标签名,如 'code_review'
"""
# 提取 XML 片段
pattern = rf'<{root_tag}[\s\S]*?{root_tag}>'
match = re.search(pattern, text, re.DOTALL)
if not match:
return None
try:
return ET.fromstring(match.group(0))
except ET.ParseError:
return None
def parse_code_review(xml_output: str) -> dict:
"""解析代码审查 XML 结果"""
root = extract_xml(xml_output, "code_review")
if root is None:
return {}
issues = []
for issue in root.findall(".//issue"):
issues.append({
"severity": issue.get("severity"),
"location": issue.findtext("location", ""),
"description": issue.findtext("description", ""),
"fix": issue.findtext("fix", ""),
})
return {
"summary": root.findtext("summary", ""),
"score": int(root.findtext("score", "0")),
"issues": issues,
"approved": root.findtext("approved", "false").lower() == "true",
}
# 使用示例
xml_response = """
<code_review>
<summary>代码结构合理,但存在SQL注入风险</summary>
<score>62</score>
<issues>
<issue severity="critical">
<location>第15行 get_user函数</location>
<description>直接拼接用户输入到SQL查询中,存在SQL注入风险</description>
<fix>使用参数化查询替代字符串拼接</fix>
</issue>
</issues>
<approved>false</approved>
</code_review>
"""
result = parse_code_review(xml_response)
print(result)
# {'summary': '...', 'score': 62, 'issues': [...], 'approved': False}
4.3 XML 在 Prompt 中标记不同部分(Anthropic 推荐用法)
<task>
分析以下两个合同版本的差异,找出对甲方不利的变化
</task>
<contract_v1>
[原合同文本]
</contract_v1>
<contract_v2>
[修改后合同文本]
</contract_v2>
<output_format>
以 XML 格式返回:
<analysis>
<change risk="high|medium|low">
<clause>条款名称</clause>
<v1>原文</v1>
<v2>修改后</v2>
<impact>对甲方的影响</impact>
</change>
</analysis>
</output_format>
五、纯文本格式控制
5.1 完全禁用所有格式(语音/短信场景)
# System Prompt 你的输出将被转换为语音播报(TTS),必须严格遵守: - 禁止所有 Markdown 符号(* # ` - = > 等) - 禁止使用项目列表 - 禁止使用表格 - 使用完整的自然语言句子,用句号分隔 - 数字写成文字(3 → 三,100% → 百分之百) - 英文缩写展开(API → 接口,AI → 人工智能) - 每段话不超过50字,方便听众理解
5.2 控制纯文本的段落结构
用纯文本格式回答(不用 Markdown),但遵守以下排版规则: - 每个主要观点单独成段 - 段落之间空一行 - 每段不超过4句话 - 如果需要列举,用中文括号加序号:(1)(2)(3) - 如需强调,用书名号或引号包裹关键词
六、多格式混合输出
某些场景需要在同一个响应中混合使用多种格式——比如分析报告的正文用 Markdown,提取的数据用 JSON:
分析以下财务报告,分两个部分输出:
**第一部分:分析报告**
用 Markdown 格式,包含概述、关键发现、风险提示三个章节。
**第二部分:结构化数据**
在报告后,输出以下 JSON 数据块(用 ```json 包裹):
{
"revenue": 数字(万元),
"profit_margin": 百分比数字,
"risk_level": "low|medium|high",
"key_metrics": {"指标名": 数值}
}
报告内容:[财务报告文本]
混合输出解析代码
import json
import re
def parse_mixed_output(text: str) -> dict:
"""
解析包含 Markdown 报告 + JSON 数据的混合输出
"""
# 提取 JSON 代码块
json_match = re.search(r'```json\s*([\s\S]*?)\s*```', text)
structured_data = None
if json_match:
try:
structured_data = json.loads(json_match.group(1))
except json.JSONDecodeError:
pass
# 提取 Markdown 报告(去掉 JSON 部分)
markdown_report = re.sub(r'```json[\s\S]*?```', '', text).strip()
return {
"report_markdown": markdown_report,
"structured_data": structured_data,
}
# 使用示例
output = """
## 财务分析报告
### 概述
公司本季度营收增长显著...
### 关键发现
- **营收**:达到 1200 万元,同比增长 23%
- **利润率**:维持在 18% 左右
```json
{
"revenue": 1200,
"profit_margin": 18,
"risk_level": "low",
"key_metrics": {"growth_rate": 23, "cash_ratio": 2.1}
}
```
"""
result = parse_mixed_output(output)
print("报告:", result["report_markdown"][:50])
print("数据:", result["structured_data"])
七、格式一致性保障(批量处理场景)
在需要处理大量数据的场景,格式一致性至关重要。以下是确保批量输出格式统一的最佳实践:
import anthropic
import json
from typing import Any
client = anthropic.Anthropic()
# 把格式要求放在 System Prompt 里,对所有请求统一生效
STRICT_JSON_SYSTEM = """
你是一个数据处理助手,所有输出都必须是合法的 JSON。
严格规则:
1. 只输出 JSON,绝对不要有任何前后缀文字
2. 不使用 Markdown 代码块(```)
3. 所有字符串值用双引号(不用单引号)
4. 数值不要加引号
5. 布尔值用 true/false(小写)
6. 空值用 null
"""
def batch_classify(texts: list[str]) -> list[dict]:
"""批量分类,确保每条输出格式一致"""
results = []
schema = '{"text_id": integer, "category": "string", "confidence": float_0_to_1}'
for i, text in enumerate(texts):
response = client.messages.create(
model="claude-haiku-4-5-20251001", # 批量分类用 Haiku 节省成本
max_tokens=128,
system=STRICT_JSON_SYSTEM,
messages=[{
"role": "user",
"content": f"分类文本(id={i}):{text}\n输出schema:{schema}"
}]
)
raw = response.content[0].text.strip()
# 去掉可能的代码块标记
raw = re.sub(r'^```(?:json)?\s*|\s*```$', '', raw).strip()
try:
result = json.loads(raw)
results.append(result)
except json.JSONDecodeError:
# 解析失败时返回错误占位
results.append({
"text_id": i,
"category": "parse_error",
"confidence": 0.0,
"raw_output": raw
})
return results
八、常见格式问题速查表
| 问题现象 | 原因 | 解决方案 |
|---|---|---|
| JSON 前后有解释文字 | Claude 默认习惯加说明 | System Prompt 强调”只输出JSON”,或用代码提取 JSON 部分 |
| JSON 被 ` ` ` 包裹 | Claude 认为代码块更清晰 | 明确禁止代码块,或在解析时用正则提取 |
| 纯文本场景出现 **粗体** | Claude 在没有指令时倾向美化输出 | System Prompt 明确禁止 Markdown |
| 批量处理格式不一致 | 每次请求可能有微小的格式差异 | 固定 System Prompt + 健壮的解析容错逻辑 |
| XML 标签属性用单引号 | 两种引号都合法,Claude 随机选择 | 在 Prompt 中明确”属性值用双引号” |
| JSON 数字字段被加了引号 | Claude 不确定时可能保守处理 | 在 schema 中明确标注”数字类型,不加引号” |
常见问题
Q:JSON 和 XML 怎么选?
JSON 更适合程序间数据交换(解析库丰富,语法更简洁);XML 更适合包含大量文本内容的结构化文档(能更自然地嵌套长文本,Claude 对 XML 标签响应也特别好)。API 开发通常选 JSON;文档处理、内容标注选 XML。两者都没有绝对优劣,按你的下游系统来决定。
Q:Claude 偶尔还是会输出不符合格式的内容,怎么办?
接受一定的失败率,做好容错处理。生产环境中,建议设置最多3次重试,每次失败后在 Prompt 里加强格式强调。同时维护一个”解析失败”的记录,定期审查这些案例,优化你的格式 Prompt。完全零失败率的格式约束在生产中很难实现,重要的是失败时程序不崩溃。
Q:用 claude.ai 网页端时,能关闭 Markdown 渲染吗?
目前 claude.ai 网页端没有关闭 Markdown 渲染的开关。如果你不想看到渲染后的格式,可以在 Prompt 里要求”用纯文本输出,不使用任何 Markdown 符号”,这样输出本身就不会有格式符号。
总结
格式控制的核心原则只有一条:明确告诉 Claude 你要什么格式,而不是期望它猜。最有效的位置是 System Prompt——在这里设置格式规则,对整个会话生效,不需要每次重复。生产环境中,JSON 解析一定要加容错逻辑,因为完全稳定的格式输出在实践中难以实现。XML 标签不只用于输出,还是组织复杂 Prompt 的有效工具——这一点很多人没有充分利用。