From 09a164cac9c80c6c8b251b5f0fd4072c2d220e87 Mon Sep 17 00:00:00 2001 From: reluc Date: Wed, 18 Mar 2026 17:00:28 +0100 Subject: [PATCH] feat(isJson): allow any valid JSON value to pass (rfc8259) fix #2183 --- README.md | 2 +- src/lib/isJSON.js | 9 ++++++++- test/validators.test.js | 23 +++++++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fe57761a5..107684d29 100644 --- a/README.md +++ b/README.md @@ -137,7 +137,7 @@ Validator | Description **isISO4217(str)** | check if the string is a valid [ISO 4217][ISO 4217] officially assigned currency code. **isISRC(str)** | check if the string is an [ISRC][ISRC]. **isISSN(str [, options])** | check if the string is an [ISSN][ISSN].

`options` is an object which defaults to `{ case_sensitive: false, require_hyphen: false }`. If `case_sensitive` is true, ISSNs with a lowercase `'x'` as the check digit are rejected. -**isJSON(str [, options])** | check if the string is valid JSON (note: uses JSON.parse).

`options` is an object which defaults to `{ allow_primitives: false }`. If `allow_primitives` is true, the primitives 'true', 'false' and 'null' are accepted as valid JSON values. +**isJSON(str [, options])** | check if the string is valid JSON (note: uses JSON.parse).

`options` is an object which defaults to `{ allow_primitives: false, allow_any_value: false }`. If `allow_primitives` is true, the primitives 'true', 'false' and 'null' are accepted as valid JSON values. If `allow_any_value` is true, any string that passes JSON.parse is cosidered valid. **isJWT(str)** | check if the string is valid JWT token. **isLatLong(str [, options])** | check if the string is a valid latitude-longitude coordinate in the format `lat,long` or `lat, long`.

`options` is an object that defaults to `{ checkDMS: false }`. Pass `checkDMS` as `true` to validate DMS(degrees, minutes, and seconds) latitude-longitude format. **isLength(str [, options])** | check if the string's length falls in a range and equal to any of the integers of the `discreteLengths` array if provided.

`options` is an object which defaults to `{ min: 0, max: undefined, discreteLengths: undefined }`. Note: this function takes into account surrogate pairs. diff --git a/src/lib/isJSON.js b/src/lib/isJSON.js index 5c51dd31c..a59d25a61 100644 --- a/src/lib/isJSON.js +++ b/src/lib/isJSON.js @@ -4,18 +4,25 @@ import merge from './util/merge'; const default_json_options = { allow_primitives: false, + allow_any_value: false, }; export default function isJSON(str, options) { assertString(str); try { options = merge(options, default_json_options); + const obj = JSON.parse(str); + + // Strict RFC validation anything that parse is JSON + if (options.allow_any_value) { + return true; + } + let primitives = []; if (options.allow_primitives) { primitives = [null, false, true]; } - const obj = JSON.parse(str); return includes(primitives, obj) || (!!obj && typeof obj === 'object'); } catch (e) { /* ignore */ } return false; diff --git a/test/validators.test.js b/test/validators.test.js index 1fa629092..4279a2ede 100644 --- a/test/validators.test.js +++ b/test/validators.test.js @@ -7238,6 +7238,29 @@ describe('Validators', () => { }); }); + it('should validate JSON with any value', () => { + test({ + validator: 'isJSON', + args: [{ allow_any_value: true }], + valid: [ + '{ "key": "value" }', + '{}', + 'null', + 'false', + 'true', + '"RFC8259"', + '42', + ], + invalid: [ + '{ key: "value" }', + '{ \'key\': \'value\' }', + '{ "key": value }', + '01234', + "'nope'", + ], + }); + }); + it('should validate multibyte strings', () => { test({ validator: 'isMultibyte',