/^/
MediumWeb6 min read

JSON Value Token Regex

Matches a single JSON scalar value: a double-quoted string, a JSON-formatted number, or one of the literals true, false, or null.

#json#web#parsing#data-format#validation#value

Regex Pattern

^(?:"(?:[^"\\]|\\.)*"|-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?|true|false|null)$

Pattern Breakdown

Hover over a token to see what it does.

^(?:"(?:[^"\\]|\\.)*"|-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?|true|false|null)$
TokenMeaning
"(?:[^"\\]|\\.)*"A JSON string: an opening quote, any run of non-quote/non-backslash characters or backslash-escaped sequences, then a closing quote
[^"\\]Any character inside the string that is not a quote or a backslash
\\.An escaped character such as \n, \", or \\
-?An optional leading minus sign for negative numbers
(?:0|[1-9]\d*)The integer part: either a single zero or a non-zero digit followed by more digits (no leading zeros)
(?:\.\d+)?An optional fractional part
(?:[eE][+-]?\d+)?An optional exponent part
true|false|nullThe three JSON literal keywords

Detailed Explanation

What it does

This pattern validates that a string is a single, well-formed JSON scalar value on its own, not an object or array. It accepts JSON strings with proper escape sequences, JSON numbers with the strict no-leading-zero rule, and the literals true, false, and null.

Why it works

Each alternative in the top-level group models one JSON value grammar rule exactly: the string branch mirrors the JSON spec's escape handling, the number branch enforces that integers either are zero or start with a non-zero digit, and the literal branches are simple fixed keywords. Anchoring with ^ and $ ensures the entire input is one value, not just a value embedded in a larger string.

Common use cases

  • Validating a single form field or config value before wrapping it into a JSON payload
  • Highlighting JSON value tokens in a syntax highlighter or lightweight JSON viewer
  • Quick sanity-checking of extracted values in a log-scraping or config-templating tool
  • Building a hand-rolled JSON tokenizer for teaching or debugging purposes

Edge cases

  • Leading zeros like 0123 are correctly rejected since the integer branch disallows them
  • Escaped quotes inside strings, like "say \"hi\"", are matched because \. consumes the backslash and the escaped quote together
  • Negative zero, -0, is accepted since the number grammar allows an optional minus before a single zero
  • Scientific notation such as 1.5e10 or 2E-3 is matched by the optional exponent group

Limitations

  • This pattern only validates a single scalar value and does not handle JSON objects or arrays
  • It does not verify that a string's escape sequences (like \uXXXX) are valid Unicode code points
  • Extremely large numeric literals are matched syntactically but may lose precision when parsed as a JavaScript number

Interactive Tester

Edit the pattern or text below — matching runs live in your browser.

"hello" 42 -3.14

Test Cases

Editable — add your own inputs to see if they pass.

InputExpectedResult
Pass
Pass
Pass
Pass
Pass
Pass
Pass
Pass
Pass
Pass

Language Variants

Production-ready examples in 12 languages.

const jsonValueRegex = /^(?:"(?:[^"\\]|\\.)*"|-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?|true|false|null)$/;
console.log(jsonValueRegex.test('42')); // true

Common Mistakes

Allowing leading zeros in the integer part, e.g. writing \d+ instead of (?:0|[1-9]\d*), which lets invalid numbers like 007 pass

Fix: Use (?:0|[1-9]\d*) so a lone zero is allowed but multi-digit numbers can't start with zero

Forgetting to allow escaped characters inside strings, causing valid JSON strings with \" or \\ to fail

Fix: Add the \\. alternative alongside [^"\\] so any backslash-escaped character is consumed as a unit

Anchoring only with $ or only with ^, which allows partial matches inside a larger string

Fix: Always pair ^ and $ (or use full-string matching APIs) when validating a value, not just extracting one

Performance Notes

  • The alternation is ordered so common cases (strings, then numbers) are tried early, but all branches are still checked linearly with no exponential blowup
  • The string branch's (?:[^"\\]|\\.)* can backtrack character-by-character on malformed input, but it's still linear because each branch consumes at least one character
  • For validating many values in a loop, compile the RegExp once outside the loop rather than re-creating the literal each time

Browser Compatibility

EngineSupportedNotes
ChromeYes
FirefoxYes
SafariYes
EdgeYes
Node.jsYes