Storing Multi-Line Strings in JSON with JSONLint
JSON remains the foundation of configuration files, API payloads, and—increasingly—prompt engineering workflows. While its strict syntax ensures data portability, it also presents a challenge: raw line breaks are invalid within JSON strings. This limitation frequently affects developers working with SSH keys, certificates, SQL queries, or extensive Markdown blocks.
With the rise of generative AI technologies, JSON has become even more essential, now powering:
- OpenAI function calling & tool invocation – where arguments must conform to strict JSON standards
- Prompt-engineering frameworks (LangChain, LlamaIndex) that transmit multi-line prompts and code snippets
- JSONL corpora designed for fine-tuning Large Language Models
- Vector-store metadata where document chunks require newline-friendly formatting
This guide offers three production-ready storage techniques, best practices for AI prompts, and power tips you can immediately implement in your pipeline.
Why Multi-Line Strings Matter in the AI Era
| AI Use-Case | Why Newlines Are Critical |
|---|---|
| Prompt templates | System or user prompts frequently include code blocks and Markdown formatting |
| Function calling | You may need to pass complete JSON schemas or SQL queries as arguments |
| RAG ingestion | Chunked documents stored as JSONL require intact paragraph breaks for quality embeddings |
| Fine-tuning | Conversation histories in JSONL depend on newline-preserved content for training accuracy |
Tip: Storing prompts or documents as an array of lines maintains clean training data and prevents models from hallucinating missing line breaks.
TL;DR
- JSON strings cannot contain literal newlines; they must be escaped
- The most readable approach: store each line as an array element and use
join("\n")at runtime - Alternatives: escape \n within a single long string or base64-encode the entire content
- Always generate JSON with a standards-compliant library—
JSON.stringify,json.dumps, etc.—rather than manually concatenating strings - Validate with JSONLint or our open-source JSON validation CLI for immediate feedback
Stop Hand-Rolling JSON (Best Practice)
“Use a standards-compliant JSON library instead of constructing raw strings like a monster.” — every experienced engineer
Manually constructing JSON through string concatenation is fragile and unsafe. Libraries:
- Guarantee validity (proper escaping, no stray commas)
- Prevent injection vulnerabilities when untrusted data is interpolated
- Enhance maintainability—you modify objects, not delicate text strings
Implementation Examples
JavaScript / Node
const promptTemplate = [
"You are a helpful assistant.",
"Answer with JSON only.",
userMarkdown // multiline Markdown from the front-end
];
const payload = {
model: "gpt-4o",
messages: [{ role: "user", content: promptTemplate.join("\n") }]
};
fetch("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${key}`
},
body: JSON.stringify(payload)
});
Python
import json, base64
payload = {
"publicKeyB64": base64.b64encode(b"...pem bytes...").decode()
}
print(json.dumps(payload, indent=2))
1. Array-of-Lines Pattern (Most Readable)
{
"servers": {
"servername.com": {
"publicKey": [
"-----BEGIN PUBLIC KEY-----",
"MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0VmDBbzXdgubV/X8JP9B",
"...snip...",
"-----END PUBLIC KEY-----"
]
}
}
}
At runtime:
const publicKey = data.servers["servername.com"].publicKey.join("\n");
Pros: Human-readable, diff-friendly, works with any JSON parser, no additional decode step required.
Cons: Slightly larger payload size; must remember to join().
2. Escaped Newlines (Compact but Less Readable)
{
"prompt": "You are a helpful assistant.\n\nYour job is to answer questions clearly and concisely."
}
Quality editors highlight \n sequences, but large text blocks become difficult to compare. This format represents how your JSON will ultimately look after serialization by a standard library. Remember that you should never manually insert escape sequences yourself—always use proper serialization libraries like JSON.stringify() or json.dumps() to ensure correct escaping and avoid subtle bugs.
3. Base64 Encoding (Required for Binary Data)
{
"publicKeyB64": "LS0tLS1CRUdJTiBQVUJMSU...=="
}
import { Buffer } from "node:buffer";
const publicKey = Buffer.from(data.publicKeyB64, "base64").toString("utf8");
Ideal for certificates (PEM/DER), images, or any binary content that doesn’t require visual inspection.
Designing Prompt Schemas (Metadata-First DSL)
Rather than delivering a single monolithic prompt string, many engineering teams now structure prompts as organized fields—effectively creating a domain-specific language (DSL) built on JSON:
{
"system": "You are a helpful assistant.",
"instructions": "Always respond in a calm, informative tone.",
"example_input": "What is the capital of France?",
"example_output": "The capital of France is Paris."
}
Benefits
- Clear separation between system message, user instructions, and examples
- Easier to tokenize, version-control, and troubleshoot than a massive text block
- Compatible with OpenAI function calling and other schema-driven APIs
Store Prompts as Markdown → Compile to JSON
For maximum readability with non-technical stakeholders, maintain prompts in plain Markdown (.md or .prompt) and compile them during your build process:
prompt.md
You are a contract-lawyer AI.
Your task is to:
1. Summarize obligations
2. List liabilities
3. Flag deadlines
build.js
import fs from "fs";
const prompt = fs.readFileSync("prompt.md", "utf8");
const job = { role: "system", content: prompt.replace(/\r?\n/g, "\n") };
fs.writeFileSync("prompt.json", JSON.stringify(job));
Validation & Linting
Before committing your changes, run:
jsonlint config.json
or paste your JSON into JSONLint. Both tools immediately identify stray control characters.
Security Considerations
| Security Concern | Key Considerations |
|---|---|
| Injection Risks |
• Array-of-Lines pattern isolates potentially malicious strings • Always validate input before parsing to prevent JSON injection • For user-generated content, add sanitization beyond standard JSON escaping |
| Sensitive Data Handling |
• Avoid storing credentials directly in JSON config files • Prefer environment variables or secret-management services for API keys & certs • If secrets must reside in JSON, enforce access controls and encrypt at rest |
| Transmission Security |
• Base64 is encoding, not encryption—offers no security alone • Always transmit JSON over HTTPS/TLS • Use field-level encryption for highly sensitive values in payloads |
| Cross-Site Scripting (XSS) |
• Be cautious when deserializing & rendering user-provided multi-line content • Apply context-appropriate output encoding before displaying stored JSON strings |
Need senior JavaScript & AI engineers who pay attention to these details? Hire proven developers in days—not weeks.