<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Harsh Verma</title>
    <description>The latest articles on Forem by Harsh Verma (@harsh_verma_b9e42904b2398).</description>
    <link>https://forem.com/harsh_verma_b9e42904b2398</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1513950%2F2d989bfe-9dd8-44ef-8fae-7074d2dd111b.jpg</url>
      <title>Forem: Harsh Verma</title>
      <link>https://forem.com/harsh_verma_b9e42904b2398</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/harsh_verma_b9e42904b2398"/>
    <language>en</language>
    <item>
      <title>Stop using regex to fix LLM JSON. I built a middleware for it.</title>
      <dc:creator>Harsh Verma</dc:creator>
      <pubDate>Sat, 28 Feb 2026 16:28:48 +0000</pubDate>
      <link>https://forem.com/harsh_verma_b9e42904b2398/stop-using-regex-to-fix-llm-json-i-built-a-middleware-for-it-3dgn</link>
      <guid>https://forem.com/harsh_verma_b9e42904b2398/stop-using-regex-to-fix-llm-json-i-built-a-middleware-for-it-3dgn</guid>
      <description>&lt;p&gt;If you are building an AI wrapper, a RAG pipeline, or working with Agentic AI, you already know the dirtiest secret in the space:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LLMs are terrible at returning reliable JSON.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can use OpenAI's JSON mode. You can write strict system prompts. But eventually, in a production environment, the model will hallucinate a trailing comma, use single quotes, or just forget a closing bracket.&lt;/p&gt;

&lt;p&gt;And when that hits your Node backend?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;llmOutput&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 💥 Crashes your Express server thread.&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I got tired of writing brittle Regex hacks to catch trailing commas, so I built a dedicated API and open-sourced the SDKs to fix it permanently.&lt;/p&gt;

&lt;p&gt;Here is how I built a "Reliability Layer" that auto-repairs JSON and validates it against a schema before it ever touches your database.&lt;/p&gt;




&lt;h3&gt;
  
  
  Why "Just use Regex" is a trap
&lt;/h3&gt;

&lt;p&gt;When we first hit the &lt;code&gt;SyntaxError: Unexpected token&lt;/code&gt; bug, the reflex is to write a utility function:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Strip the

```&lt;code&gt;json&lt;/code&gt; markdown.&lt;/li&gt;
&lt;li&gt;Regex out the trailing commas.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This works until the LLM nests a broken object inside an array, or completely omits a required key that your Postgres database is expecting. Wrapping it in a &lt;code&gt;try/catch&lt;/code&gt; just means you drop the data entirely and have to waste tokens re-prompting the AI.&lt;/p&gt;

&lt;p&gt;Large Language Models generate probabilistic text. Backends require deterministic structure. You can't mix the two without a shield in the middle.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Architecture: &lt;code&gt;llm-json-guard&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;I built &lt;a href="https://www.google.com/search?q=https://www.npmjs.com/package/llm-json-guard" rel="noopener noreferrer"&gt;llm-json-guard&lt;/a&gt; (available on NPM and PyPI).&lt;/p&gt;

&lt;p&gt;Instead of doing the heavy lifting on the client device or main server thread (which is terrible for performance), it routes the broken string to a fast RapidAPI backend I deployed called &lt;strong&gt;LLM JSON Sanitizer &amp;amp; Schema Guard&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;br&gt;
&lt;code&gt;LLM → JSON.parse() → Runtime Failure&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You do this:&lt;br&gt;
&lt;code&gt;LLM → llm-json-guard → Business Logic&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Dropping it into Express
&lt;/h3&gt;

&lt;p&gt;I wanted the SDK to be basically zero-friction. In my demo repo, I have a file called &lt;code&gt;03-express-integration.js&lt;/code&gt; that shows how it works as middleware.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
javascript
import { LLMJsonGuard } from "llm-json-guard";

const guard = new LLMJsonGuard({ apiKey: process.env.RAPIDAPI_KEY });

// The LLM hallucinated single quotes and a trailing comma
const brokenAIOutput = "{'name': 'Harsh', 'age': 21,}"; 

const result = await guard.sanitize(brokenAIOutput);



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  The "Confidence Score"
&lt;/h3&gt;

&lt;p&gt;If you look at the terminal output when you run this, it doesn't just hand you the JSON. It tells you exactly what it did.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
json
{
  "success": true,
  "stage": "parsed_only",
  "meta": {
    "repaired": true,
    "confidence": 0.88
  },
  "data": {
    "name": "Harsh",
    "age": 21
  },
  "errors": []
}



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Notice the &lt;strong&gt;&lt;code&gt;confidence: 0.88&lt;/code&gt;&lt;/strong&gt;.&lt;br&gt;
If the AI completely loses its mind and outputs a massive block of text, the repair engine has to violently alter the string to extract a JSON object. The confidence score drops. If the score is too low, your app knows to reject the payload, even if it's technically valid JSON now.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enforcing Strict Schemas
&lt;/h3&gt;

&lt;p&gt;Repairing the syntax is only step one. If your database requires an &lt;code&gt;age&lt;/code&gt; field, and the LLM just forgot to include it, valid JSON won't stop your app from breaking later.&lt;/p&gt;

&lt;p&gt;You can pass a standard JSON Schema into the &lt;code&gt;.guard()&lt;/code&gt; method.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
javascript
const userSchema = {
  type: "object",
  properties: {
    name: { type: "string" },
    age: { type: "number" }
  },
  required: ["name", "age", "role"] // Enforce the contract
};

// Returns { success: false, stage: 'validation_failed' } because 'role' is missing
const result = await guard.guard(brokenAIOutput, userSchema); 



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Benchmark
&lt;/h3&gt;

&lt;p&gt;I also ran this through a standard performance test (&lt;code&gt;04-benchmark.js&lt;/code&gt; in the repo). Because the heavy AST parsing and schema compilation is cached on the API layer, it adds minimal overhead to your request cycle while guaranteeing 100% data safety.&lt;/p&gt;

&lt;h3&gt;
  
  
  Try it out
&lt;/h3&gt;

&lt;p&gt;If you are dealing with broken LLM outputs, don't write another regex parser.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📦 &lt;strong&gt;Node.js:&lt;/strong&gt; &lt;code&gt;npm i llm-json-guard&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;🐍 &lt;strong&gt;Python:&lt;/strong&gt; &lt;code&gt;pip install llm-json-guard&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;🛠️ &lt;strong&gt;Demo Repo:&lt;/strong&gt; &lt;a href="https://github.com/harshxframe/llm-json-guard-node-demo" rel="noopener noreferrer"&gt;Check out the Express &amp;amp; benchmark examples here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🔑 &lt;strong&gt;API Key:&lt;/strong&gt; You can grab a free tier key on &lt;a href="https://rapidapi.com/scotedflotsincoltd/api/llm-json-sanitizer-schema-guard" rel="noopener noreferrer"&gt;RapidAPI here&lt;/a&gt; to test it out.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let me know what edge cases your LLMs are failing on, I'm actively updating the parsing engine to catch weirder hallucinations!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>node</category>
      <category>python</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
