I am trying to parse a string with the json.el package, though when the string is not json unexpected things happen. Is there a way in elisp to check whether or not a provided string is actually a valid json before trying to parse it with json-read-from-string
?
Asked
Active
Viewed 1,223 times
6

Drew
- 75,699
- 9
- 109
- 225

lookyhooky
- 949
- 7
- 18
-
2The only way to know if a string is valid JSON is to try to parse it as JSON. – npostavs Jul 26 '16 at 22:15
-
@npostavs So I should try to parse it and then handle the error that's thrown if its not valid json? – lookyhooky Jul 26 '16 at 22:17
-
Be aware too of what kind of "valid" (i.e., well-formed) JSON you are interested in. In practice, most applications that use JSON allow lots of syntax that is not strict JSON syntax. – Drew Jul 27 '16 at 00:19
-
1"try to parse it and then handle the error" - Yup. – npostavs Jul 27 '16 at 15:35
2 Answers
2
It's possible to use functionality provided by json
which ships with Emacs to validate a JSON. It's a matter of trying to parse a string with it and catching any errors it might spit out.
(require 'json)
(defun my-json-string-valid-p (string)
"Validates a JSON string."
(condition-case nil
(progn
(json-read-from-string string)
t)
(error nil)))
1
C-x my-validate-json-or-js-expression
validate the current buffer or selected region as json.
The only requirement is you need install js2-mode
. (No, you don't need setup js2-mode. My code works out of box! we use js2-mode as API collection instead of major-mode)
Here is the code,
(defun my-validate-json-or-js-expression (&optional not-json-p)
"Validate buffer or select region as JSON.
If NOT-JSON-P is not nil, validate as Javascript expression instead of JSON."
(interactive "P")
(let* ((json-exp (if (region-active-p) (buffer-substring-no-properties (region-beginning) (region-end))
(buffer-substring-no-properties (point-min) (point-max))))
(jsbuf-offet (if not-json-p 0 (length "var a=")))
errs
first-err
(first-err-pos (if (region-active-p) (region-beginning) 0)))
(unless not-json-p
(setq json-exp (format "var a=%s;" json-exp)))
(with-temp-buffer
(insert json-exp)
(unless (featurep 'js2-mode)
(require 'js2-mode))
(js2-parse)
(setq errs (js2-errors))
(cond
((not errs)
(message "NO error found. Good job!"))
(t
;; yes, first error in buffer is the last element in errs
(setq first-err (car (last errs)))
(setq first-err-pos (+ first-err-pos (- (cadr first-err) jsbuf-offet)))
(message "%d error(s), first at buffer position %d: %s"
(length errs)
first-err-pos
(js2-get-msg (caar first-err))))))
(if first-err (goto-char first-err-pos))))
The bonus tip is you can also C-u M-x my-validate-json-or-js-expression
to validate as javascript expression. This is only useful when you don't use js2-mode for javascript file.

chen bin
- 4,781
- 18
- 36
-
-
Yes, but in reality, the invalid json is always invalid js expression (json missing quote, bracket) – chen bin Jul 31 '16 at 03:25