锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

clisp 之 JSON解析 V1

时间:2023-09-09 20:37:02 whj1精密电位器精密电位器whj1

简单实现json字符串 解析为lisp 对象。

调用:

(whj.json:parse-json-string json-string)

(defpackage :whj.json  (:use   :cl   :ext)  (:export   :parse-json-string)) ;------------------------------------------------------------------------------- (in-package :whj.json) ;------------------------------------------------------------------------------- (defun object-begin-char-p (ch)  (if (member ch (list #\{ #\[)) t nil))  (defun object-end-char-p (ch)  (if (member ch (list #\} #\])) t nil))   (defun whitespace-p (char)     (member char '(#\tab #\space #\return #\newline)))  (defun pair-chars-p (ch1 ch2)  (or    (and (char= ch1 #\{) (char= ch2 #\}))   (and (char= ch1 #\[) (char= ch2 #\]))))  (defun next-object-start-index (json-string start-index stop-index)  (loop for i from start-index to stop-index     for ch = (char json-string i)     if (object-begin-char-p ch) do (return-from next-object-start-index i))  nil)   (defun next-object-stop-index (json-string start-index stop-index)  (loop for i from start-index to stop-index     for ch = (char json-string i)     if (object-end-char-p ch) do (return-from next-object-stop-index i))  nil)   (defun nvl? (v default-value)  (if v v default-value))   (defun trim-value (str)  (when (char= (char str 0) #\")   (setq str (subseq str 1 (1- (length str)))))  str)  (defun as-json-array (json-string object-index-list)  (let ((arr (make-array 2 :adjustable t :fill-pointer 0))     (s 1)     (e 1)     (flag nil);t:标识在字段内;nil:字符开始或结束     )   (loop for i from s below (length json-string)     do (progn      (let ((prev-char (char json-string (1- i)))         (cur-char  (char json-string i)))          (cond         ((and (null flag) (= s e) (whitespace-p cur-char)) ;前导空白字符的忽略值           (setf s (1  i) e s))         ((and (null flag) (char= cur-char #\") (char/= prev-char #\\)) ;字符串值开始            (setf flag t s i))         ((and flag (char= cur-char #\") (char/= prev-char #\\));字符串双引号匹配结束            (setf flag nil            e  (1  i)))         ((or (and (null flag) (char= cur-char #\,)) ;值结束            (and (null flag) (char= cur-char #\])))           (unless (= s e)            (let ((val (subseq json-string s e)))             (setq val (trim-value val))             (vector-push-extend val arr)))           (setf s (1  i) e s))         (flag (setq e (1  i)));在值的内部,不管是不是空白字符,都需要         ((and (null flag) (not (whitespace-p cur-char))) ;值开始          (incf e)          (let ((obj-index-pair (find i object-index-list :key 'car)))           (when obj-index-pair                        ;更新下一轮循环变量            (setf flag nil               s  (cdr obj-index-pair)               e   s               i   s)            (let ((sub-json-string (subseq json-string (car obj-index-pair) (cdr obj-index-pair))))             (vector-push-extend (parse-json-string sub-json-string) arr)))))                    )           )))   arr))   (defun as-json-hash  (json-string object-index-list)  (let ((dict (make-hash-table :test #'equal))     (s 1)     (e 1)     (flag nil);t:标识在字段内;nil:字符开始或结束     (key nil))   (loop for i from s below (length json-string)     do (let ((prev-char (char json-string (1- i)))         (cur-char  (char json-string i)))       (cond         ((and (null flag) (= s e) (whitespace-p cur-char)) ;前导空白字符的忽略值           (setf s (1  i) e s))         ((and (null flag) (char= cur-char #\") (char/= prev-char #\\)) ;字符串值开始            (setf flag t s i))         ((and flag (char= cur-char #\") (char/= prev-char #\\));字符串双引号匹配结束            (setf flag nil            e  (1  i)))         ((or (and (null flag) (char= cur-char #\,)) ;值结束           (and (null flag) (char= cur-char #\}))           (and (null flag) (char= cur-char #\:) (char/= prev-char #\\)))           (unless (= s e)            (let ((val (subseq json-string s e)))             (setq val (trim-value val))             (if (char= cur-char #\:)              (setf key val)              (setf (gethash key dict) val                 key      nil))))           (setf s (1  i) e s))         (flag (setq e (1  i)));在值的内部,不管是不是空白字符,都需要         ((and (null flag) (not (whitespace-p cur-char))) ;值开始          (incf e)          (let ((obj-index-pair (find i object-index-list :key 'car)))           (when obj-index-pair                        ;更新下一轮循环变量            (setf flag nil               s  (cdr obj-index-pair)               e   s               i   s)            (let ((sub-json-string (subseq json-string (car obj-index-pair) (cdr obj-index-pair))))             (setf (gethash key dict) (parse-json-string sub-json-string)                 key      nil)             )))));end cond           ));end loop   dict))  (defun do-prepare-json-string (json-string)  (let ((result-list nil) (stack nil)     (max-index (1- (length json-string))))      (do* ((s (next-object-start-index json-sting 0 max-index) (next-object-start-index json-string (1+ e) max-index))
			   (e (next-object-stop-index json-string (1+ s) max-index) (next-object-stop-index json-string (1+ (nvl? e max-index))  max-index)))
			   ((null e))

			   (when s
					(setf stack (cons (cons s (char json-string s)) stack))
				    ;---------------------------------------------------------------
				    ;若 s+1 和 e-1 之前还存在对象开始标志
				   (tagbody
						next
					   (setf s (next-object-start-index json-string (1+ s) (1- e)))
					   (when s
							(setf stack (cons (cons s (char json-string s)) stack))
							(go next))))
					;---------------------------------------------------------------
			   (when e
					(let* ((stack-first (car stack))
						   (si (car stack-first))
						   (si-char (cdr stack-first))
						   (ei (1+ e)))
						(when (pair-chars-p si-char (char json-string e))
							(setf result-list (cons (cons (car (car stack)) (1+ e)) result-list))
							(setf stack (cdr stack))

							(unless (car stack)
								(return-from do-prepare-json-string result-list))))))))
								

								
(defun parse-json-string (json-string)
	(let ((result-list (do-prepare-json-string json-string)))
		(let ((ch (char json-string (caar result-list))))
			(cond
				((char= ch #\[) (as-json-array json-string result-list))
				((char= ch #\{) (as-json-hash json-string result-list))
				(t (error "not impl.~a" ch))))))
;-------------------------------------------------------------------------------
;#(" tenis " "football" "1" "4")   
(defun test-01 nil
	(setf str "[\" tenis \" ,  \"football\",1,		 ,  	4        ]")
	(let ((result-list (do-prepare-json-string str)))
		(as-json-array str result-list)))
;((0 . 48) (32 . 39))
(defun test-02 nil
	(setf str02 "[\" tenis \" ,  \"football\",1,		 , [1,5,9]        ]")
	(do-prepare-json-string str02))
;array
;#(" tenis " "football" "1" #("1" "5" "9"))
(defun test-03 nil
	(setf str03 "[\" tenis \" ,  \"football\",1,		 ,[1,5,9]        ]")
	(let ((result-list (do-prepare-json-string str03)))
		(as-json-array str03 result-list)))
;hash
;#S(HASH-TABLE :TEST FASTHASH-EQUAL ("age" . "24") ("name" . "jxj"))
(defun test-04 nil
	(setf str04 "{\"name\":\"jxj\",\"age\":24}")
	(parse-json-string str04))
;#S(HASH-TABLE :TEST FASTHASH-EQUAL ("hobb" . #("tenis" "football")) ("score" . #S(HASH-TABLE :TEST FASTHASH-EQUAL ("eng" . "A") ("math" . "99"))) ("age" . "24") ("name" . "jxj"))
(defun test-05 nil
	(setf str "{\"name\":\"jxj\",\"age\":24,\"score\":{\"math\":99,\"eng\":\"A\"},\"hobb\":[\"tenis\",\"football\"]}")
	(parse-json-string str))
;-------------------------------------------------------------------------------			
(setf (ext:package-lock :whj.json) t)
;-------------------------------------------------------------------------------
锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章