landsat99 发表于 2022-4-20 11:37:54

请问,Autolisp/Visuallisp有读写Json格式的API吗?

请问,Autolisp/Visuallisp有读写Json格式的API吗?


alisp的中间数据文件,存成什么格式合适?直接append->write-line为lisp表,还是什么?

如能存json当然最好,直观查看,也与其他语言工具通用

e2002 发表于 2022-4-21 10:20:25

本帖最后由 e2002 于 2022-4-21 10:26 编辑

如果需要和其他语言共同使用这些中间数据,用json格式确实比较合适,但 AutoLISP没有现成的读写json的函数,只能自己写一个专门的函数库,当然,如果你能在github上搞个这样的开源项目就更好了,大家一起打造这个库。

landsat99 发表于 2022-4-21 11:15:27

e2002 发表于 2022-4-21 10:20
如果需要和其他语言共同使用这些中间数据,用json格式确实比较合适,但 AutoLISP没有现成的读写json的函数 ...

感谢版主提供信息。

Lisp的Json读写API,,感觉这基础功能很重要,通用数据交流的桥梁。

如果写个小Arx会方便很多。给lisp用,属性数据的CRUD都归lisp的表,Arx纯转换<表--Json>不涉及acad对象,那么版本兼容性也会不错,不挑cad版本.

e2002 发表于 2022-4-21 12:10:12

本帖最后由 e2002 于 2022-4-21 12:11 编辑

如果数据的创建和处理都在 AutoCAD内部,直接使用list即可,毕竟 LISP处理 list 数据太方便了。


只是数据的对外保存用一个 list2json函数,读取再写一个 json2list。


landsat99 发表于 2022-4-21 12:28:11

本帖最后由 landsat99 于 2022-4-21 12:35 编辑

e2002 发表于 2022-4-21 12:10
如果数据的创建和处理都在 AutoCAD内部,直接使用list即可,毕竟 LISP处理 list 数据太方便了。



嗯呢。赞同您的意见!

我对lisp不熟,刚接触。感觉Lisp作为dwg图形数据的api可能很合适,,作通用处理 计算 分析可能比较勉强。

不太确定这种以正则为主的操作,适不适合lisp写;不合适的话就作个arx小函数。

landsat99 发表于 2022-4-24 10:52:57

Github有个俄罗斯小哥发布过Autolisp-Json的 读取函数。供大家参考

代码如下
; AutoLISP JSON parser and formatter
; (c) 2015, Michel Beloshitsky <mbeloshitsky@gmail.com>
;
; TODO:
;   - Correct numbers handling
;   - Write formatter
;   - Remove parasite (list) == nil equivalence

(setq json:debug F)

(defun debug-print (text)
(if (= T json:debug)
    (princ text)))

(defun string2list (string)
(setq output (list))
(foreach charcode (vl-string->list string)
    (setq output (cons (chr charcode) output)))
(reverse output))

(defun starts-with (pfx stringlist)
(setq pfxlist (string2list pfx))
(setq result T)
(while (not (= pfxlist (list)))
    (setq x (car pfxlist))
    (setq y (car stringlist))
    (setq pfxlist (cdr pfxlist))
    (setq stringlist (cdr stringlist))
    (if (not (= x y))
      (setq result F)))
(setq result result))

(defun drop (n lst)
(while (< 0 n)
    (setq lst (cdr lst))
    (setq n (- n 1)))
(setq lst lst))

(defun take (n lst)
(setq output (list))
(while (< 0 n)
    (setq output (cons (car lst) output))
    (setq lst (cdr lst))
    (setq n (- n 1)))
(reverse output))

(defun readhex (hexlist)
(defun hex2num (hex) (cond
    ((= hex "0") 0)((= hex "1") 1)((= hex "2") 2)((= hex "3") 3)((= hex "4") 4)((= hex "5") 5)((= hex "6") 6)
    ((= hex "7") 7) ((= hex "8") 8)((= hex "9") 9)

    ((= hex "a") 10) ((= hex "b") 11) ((= hex "c") 12) ((= hex "d") 13)((= hex "e") 14) ((= hex "f") 15)
    ((= hex "A") 10) ((= hex "B") 11) ((= hex "C") 12) ((= hex "D") 13) ((= hex "E") 14) ((= hex "F") 15)
    ))
(setq output 0)
(while (not (= hexlist (list)))
    (setq output (+ (* output 16) (hex2num (car hexlist))))
    (setq hexlist (cdr hexlist))
    )
(setq output output))

(defun json:read (jsonText)
; Так как а автолиспе ниче нет, то разбор производим стейт-машиной c магазином
(setq curr-atom "")
(setq curr-key "")

(setq curr-dict (list))
(setq dict-history (list))

(defun isdigit (ch)
    (or (= ch "0") (= ch "1") (= ch "2") (= ch "3") (= ch "4") (= ch "5") (= ch "6") (= ch "7") (= ch "8") (= ch "9")))

(defun isspace (ch)
    (or (= ch " ") (= ch "\t") (= ch "\n") (= ch "\r")))

(defun push-kv ()
    (if (not (= curr-key ""))
      (setq curr-dict (cons (cons curr-key curr-atom) curr-dict)))
    (setq curr-key "")
    (setq curr-atom ""))

(setq curr-array (list))
(setq array-history (list))

(setq string-delim "")

(setq state "object")
(setq state-history (list))

(setq error-message "")
(defun report-error (message)
    (push-state "error")
    (setq error-message message)
    (setq jsonList (list)))

(defun pop-state ()
    (debug-print (strcat "\n-" state))
    (setq state (car state-history))
    (setq state-history (cdr state-history)))
(defun push-state (new-state)
    (debug-print (strcat "\n+" new-state))
    (setq state-history (cons state state-history))
    (setq state new-state))

(defun skip ()
    (setq a ""))

(setq escaping F)

(setq jsonList (string2list jsonText))
(while (not (= jsonList (list)))
    (setq ch (car jsonList))
    (setq jsonList (cdr jsonList))
    (cond
      ((= state "up") (progn
      (setq jsonList (cons ch jsonList))
      (pop-state)
      (pop-state)))

      ((= state "object") (cond
      ((isspace ch) (skip))
      ((= ch "{") (progn
          (setq dict-history (cons (list curr-key curr-dict) dict-history))
          (setq curr-key "")
          (setq curr-dict (list))
          (push-state "object-next")
          ))
      (T (report-error (strcat "Unexpected " ch " instead of { or space")))
      ))

       ((= state "object-semi") (cond
      ((isspace ch) (skip))
      ((= ch ":") (progn
          (setq curr-key curr-atom)
          (pop-state)
          (push-state "object-next")
          (push-state "value")))
      (T (report-error (strcat "Unexpected " ch " instead of : or space")))
         ))

       ((= state "object-next") (cond
      ((isspace ch) (skip))
      ((= ch "\"") (progn
          (setq jsonList (cons ch jsonList))
          (pop-state)
          (push-state "object-semi")
          (push-state "string")))
      ((= ch ",") (progn
          (push-kv)
          (pop-state)
          (push-state "object-semi")
          (push-state "string")))
      ((= ch "}") (progn
          (push-kv)
          (setq curr-atom curr-dict)
          (setq dh (car dict-history))
          (setq dict-history (cdr dict-history))
          (setq curr-key   (nth 0 dh))
          (setq curr-dict (nth 1 dh))
          (pop-state)
          (pop-state)))
      (T (report-error (strcat "Unexpected " ch " instead of , or } or space")))
         ))

      ((= state "array") (cond
      ((isspace ch) (skip))
      ((= ch "[") (progn
          (setq array-history (cons curr-array array-history))
          (setq curr-array (list))
          (push-state "array-next")
          ))
      (T (report-error (strcat "Unexpected " ch " instead of [ or space")))
      ))

      ((= state "array-next") (cond
      ((isspace ch) (skip))
      ((= ch ",") (progn
         (setq curr-array (cons curr-atom curr-array))
         (pop-state)
          (push-state "array-next")
          (push-state "value")))
      ((= ch "]") (progn
          (setq curr-array (cons curr-atom curr-array))
          (setq curr-atom (reverse curr-array))
          (setq curr-array (car array-history))
          (setq array-history (cdr array-history))
          (pop-state)
          (pop-state)
          ))
      (T (progn
          (setq jsonList (cons ch jsonList))
          (push-state "value")))
      ))
      
      ((= state "value") (cond
      ((isspace ch) (skip))
      ((= ch "\"")
          (progn
            (setq jsonList (cons ch jsonList))
            (push-state "up")
            (push-state "string")))
      ((= ch "'")
          (progn
            (setq jsonList (cons ch jsonList))
            (push-state "up")
            (push-state "string")))
      ((= ch "{")
          (progn
            (setq jsonList (cons ch jsonList))
            (push-state "up")
            (push-state "object")))
      ((= ch "[") (progn
            (setq jsonList (cons ch jsonList))
            (push-state "up")
            (push-state "array")))
      ((or (= ch "-") (isdigit ch))
          (progn
            (setq jsonList (cons ch jsonList))
            (setq curr-atom "")
            (push-state "up")
            (push-state "number")))

      ((starts-with "true" (cons ch jsonList))
          (progn
            (setq jsonList (drop 3 jsonList))
            (setq curr-atom 'true)
            (pop-state)))
      ((starts-with "false" (cons ch jsonList))
          (progn
            (setq jsonList (drop 4 jsonList))
            (setq curr-atom 'false)
            (pop-state)))
      ((starts-with "null" (cons ch jsonList))
          (progn
            (setq curr-atom 'null)
            (setq jsonList (drop 3 jsonList))
            (pop-state)))
      (T (report-error (strcat "Unexpected " ch " instead of JSON value")))
      ))

      ((= state "string") (cond
      ((isspace ch) (skip))
      ((or (= ch "'") (= ch "\""))
          (progn
            (setq curr-atom "")
            (setq string-delim ch)
            (push-state "instring")
          ))
      (T (report-error (strcat "Unexpected " ch " instead of \" or space")))
      ))

      ((= state "instring") (cond
          (escaping   (progn
            (setq curr-atom (strcat curr-atom ch))
            (setq escaping F)))
          ((= ch "\\")
            (progn
            (setq ext (car jsonList))
            (setq jsonList (cdr jsonList))
            (cond
                ((= ext "\\") (setq curr-atom (strcat curr-atom "\\")))
                ((= ext "\"") (setq curr-atom (strcat curr-atom "\"")))
                ((= ext "/")(setq curr-atom (strcat curr-atom "/")))
                ((= ext "b")(setq curr-atom (strcat curr-atom (chr 8))))
                ((= ext "f")(setq curr-atom (strcat curr-atom (chr 12))))
                ((= ext "n")(setq curr-atom (strcat curr-atom (chr 10))))
                ((= ext "r")(setq curr-atom (strcat curr-atom (chr 13))))
                ((= ext "t")(setq curr-atom (strcat curr-atom (chr 9))))
                ((= ext "u")(progn
                  (setq curr-atom (strcat curr-atom (chr (readhex (take 4 jsonList)))))
                  (setq jsonList (drop 4 jsonList))
                  )))
                ))
          ((= ch string-delim)
            (progn
            (pop-state)
            (pop-state)))
          (T (setq curr-atom (strcat curr-atom ch)))
      ))
      
      ((= state "number") (cond
      ((or (isdigit ch) (= ch ".") (= ch "e") (= ch "E") (= ch "-") (= ch "+"))
          (setq curr-atom (strcat curr-atom ch)))
      (T (progn
          (setq curr-atom (atof curr-atom))
          (setq jsonList (cons ch jsonList))
          (pop-state)
          ))
      ))

      ((= state "error") (skip))

      (T (report-error (strcat "UnexpectedJSON parser state")))
      ))
(if (not (= state "error"))
    (setq curr-atom curr-atom)
    (progn
      (princ (strcat error-message "\n"))
      (setq curr-atom nil))
))


;(defun json:write (obj)
;...)

landsat99 发表于 2022-4-24 11:03:08

本帖最后由 landsat99 于 2022-4-24 11:04 编辑

Github另一位小哥的 Alisp-Json的读写函数。

The functions included in json_util.lsp:
_ json_to_list: Return a list with the elements of a string in json format
_ list_to_json: Return a string in json format from a list



;*************************************************************************************************
;* INICIO json_util.lsp
;*************************************************************************************************

;;-----------------------------------------------------------------------------------------
;;str_replace function.
;;Replace all aparisions of "patt" by "repl_to"
;;
;;Params:
;;-str: The original string
;;-patt: The pattern which will be replaced
;;-repl_to: The string which will replace the pattern
;;
;;Original Code by: diegomcas, 2020/03/25
;-----------------------------------------------------------------------------------------
(defun dmc:json:str_replace (str patt repl_to / pos inc init_search)

(if (not str) (setq str ""))
(if (and (not patt) (< (strlen patt) 1)) (setq patt " "))
(if (and (not repl_to) (< (strlen repl_to) 1)) (setq repl_to " "))

(setq pos (vl-string-search patt str))
(setq inc (1+ (- (strlen repl_to) (strlen patt))))
; (princ "pos= ") (princ pos) (princ "\n")
; (princ "inc= ") (princ inc) (princ "\n")
(while pos
    (setq str (vl-string-subst repl_to patt str pos))
    (setq init_search (+ pos inc))
    (if (< init_search 0)
      (setq init_search 0)
    )
    (setq pos (vl-string-search patt str init_search))
)
str
)

;;-----------------------------------------------------------------------------------------
;;json_parser function (To be executed by json_to_list)
;;Make a list of list with all data of the json string.
;;One list for each of:
;;-pairs name:value
;;-arrays
;;-objets
;;
;;Params:
;;-lst_json: The list prepared by (json_to_list) function
;;-state:for the use of the States Machine
;;
;;Original Code by: diegomcas, 2020/03/25
;;Modified 2021/03/09
;;-----------------------------------------------------------------------------------------
(defun dmc:json:json_parser (lst_json state array_lvl quote_array / lst str_name res)

(setq lst '())
(setq lst_pair '())

(if (not state)
    (setq state 'Obj)
)

(if (not array_lvl)
    (setq array_lvl 0)
)

(foreach res lst_json
    ; (princ "res= ") (princ res) (princ "\n")
    ; (princ "state= ") (princ state) (princ "\n")
    ; (princ "str_name= ") (princ str_name) (princ "\n")
    ; (princ "array_lvl= ") (princ array_lvl) (princ "\n")
    ; (princ "--------------------------------------------") (princ "\n")

    (cond
      ;Case -> reading '<ARRAY>
      ((eq res (quote <ARRAY>))
      (setq array_lvl (1+ array_lvl))
      (setq state 'Array)
      (if quote_array
          (setq lst (append lst (list res)))
      )
      )
      
      ;Case -> reading '</ARRAY>
      ((eq res (quote </ARRAY>))
      (setq array_lvl (1- array_lvl))
      (setq state 'Obj)
      (if quote_array
          (setq lst (append lst (list res)))
      )
      )

      ;Case -> { null/true/false }
      ((and (eq state 'Obj) (or (eq res 'null) (eq res 'false) (eq res 'true)))
      (setq lst (append lst (list res)))
      )

      ;Case -> {name : value} / value = 'null or 'false or 'true or 'STR or 'INT or 'REAL
      ((and (eq state 'Obj_Value) (or (eq res 'null) (eq res 'false) (eq res 'true) (eq (type res) 'STR) (eq (type res) 'INT) (eq (type res) 'REAL)))
      (if (eq 'STR (type res))
          (progn
            (setq res (dmc:json:str_replace res " , " "," ))
            (setq res (dmc:json:str_replace res " : " ":" ))
            (setq res (dmc:json:str_replace res "( <ARRAY> ""["))
            (setq res (dmc:json:str_replace res " </ARRAY> )""]"))
          )
      )
      (setq lst_pair (cons str_name res))
      (setq lst (append lst (list lst_pair)))
      (setq str_name nil)
      )
      
      ;Case -> finish reading VALUE
      ((and (eq state 'Obj_Value) (eq res ',))
      (setq state 'Obj)
      )
      
      ;Case -> Reading a name {NAME : value}
      ((and (eq state 'Obj) (eq (type res) 'STR))
      (setq res (dmc:json:str_replace res " , " "," ))
      (setq res (dmc:json:str_replace res " : " ":" ))
      (setq res (dmc:json:str_replace res "( <ARRAY> ""["))
      (setq res (dmc:json:str_replace res " </ARRAY> )""]"))

      (setq str_name res)
      (setq state 'Obj_Name)
      )
      
      ;Case -> Reading a new Object
      ((and (eq state 'Obj) (eq (type res) 'LIST))
      (setq lst_temp (dmc:json:json_parser res state array_lvl quote_array))
      (setq lst_pair (cons str_name lst_temp))
      (setq lst (append lst (list lst_pair)))
      )
      
      ;Case -> Reading a value = {Object}
      ((and (eq state 'Obj_Value) (eq (type res) 'LIST))
      (setq lst_temp (dmc:json:json_parser res 'Obj array_lvl quote_array))
      (if str_name
          (setq lst_pair (cons str_name (list lst_temp)))
          (setq lst_pair lst_temp)
      )
      
      (setq lst (append lst (list lst_pair)))
      )
      
      ;Case -> Reading a complete name {NAME : value} -> Preparing to read value
      ((and (eq state 'Obj_Name) (eq res ':))
      (setq state 'Obj_Value)
      )
      
      ;Case -> Reading an Array
      ((and (eq state 'Array) (eq (type res) 'LIST))
      (setq lst_temp (dmc:json:json_parser res nil array_lvl quote_array))
      (if str_name
          (setq lst_pair (cons str_name (list lst_temp)))
          (setq lst_pair lst_temp)
      )
      (setq lst (append lst (list lst_pair)))
      )

      ;Case -> ARRAY value = 'null or 'false or 'true or 'STR or 'INT or 'REAL without name
      ((and (and (> array_lvl 0) (eq state 'Array)) (or (eq res 'null) (eq res 'false) (eq res 'true) (eq (type res) 'STR) (eq (type res) 'INT) (eq (type res) 'REAL)))
      ; (princ res) (princ "\n")
      (setq lst (append lst (list res)))
      )

    )
)
lst
)

;;-----------------------------------------------------------------------------------------
;;json_to_list function
;;Make a list of list with all data of the json string.
;;One list for each of:
;;-pairs name:value
;;-arrays
;;-objets
;;
;;Params:
;;-json: The json string (Strings values must not contain "(" ")")
;;
;;Original Code by: diegomcas, 2020/03/25
;;-----------------------------------------------------------------------------------------
(defun dmc:json:json_to_list (json quote_array / strtransf stread)
(if (not (eq 'STR (type json)))
    (setq json "{}")
)

;Lists of lists for registers/arrays/objects of the json
(setq strtransf (vl-string-translate "{}" "()" json))
(setq strtransf (dmc:json:str_replace strtransf "[" "( <ARRAY> "))
(setq strtransf (dmc:json:str_replace strtransf "]" " </ARRAY> )"))
;add spaces before "," / Repairing bad read of numbers
(setq strtransf (dmc:json:str_replace strtransf "," " , "))
(setq strtransf (dmc:json:str_replace strtransf ":" " : "))

(setq stread (read strtransf))
;(princ "json -> ")(princ json) (princ "\n")
;(princ "stread -> ")(princ stread) (princ "\n")

(dmc:json:json_parser stread nil 0 quote_array)
)

;;-----------------------------------------------------------------------------------------
;;list_to_json function
;;Make a json string with all data of the json list.
;;
;;Not complete testing!!! Testing for use it!!!
;;Params:
;;-lst: The list of which will be written the json
;;
;;Autolisp don't have Arrays, so it is impossible to rebuild a json that contains them.
;;This function assume the list is Array Quote
;;
;;If you run (list_to_json (json_to_list "{your_json}"))
;;you probably lose data (type of data)
;;
;;Original Code by: diegomcas, 2020/03/25
;;Modified 2021/03/09
;;-----------------------------------------------------------------------------------------
(defun dmc:json:list_to_json (lst / lst_element json reading_val init_state value_to_string is_value is_attribute_simple is_attribute_complex is_array)

; (defun is_object (lst / )
    ; (and (eq (length lst) 2) (eq 'STR (type (car lst))) (not (is_array lst)))
; )

(defun value_to_string (element / )
    (cond
      ((eq 'STR (type element))
      (strcat "\"" element "\"")
      )
      ((eq 'REAL (type element))
      (rtos element 2 8)
      )
      ((eq 'INT (type element))
      (itoa element)
      )
      ((eq 'NULL element)
      "null"
      )
      ((eq 'FALSE element)
      "false"
      )
      ((eq 'TRUE element)
      "true"
      )
    )
)

(defun is_value (val / )
    (or
      (= (type val) 'STR)
      (= (type val) 'REAL)
      (= (type val) 'INT)
      (= 'NULL val)
      (= 'FALSE val)
      (= 'TRUE val)
    )
)

(defun is_attribute_simple (lst / )
    (and (is_value (cdr lst)) (eq 'STR (type (car lst))) (not (is_array lst)))
)

(defun is_attribute_complex (lst / )
    (and (= 'LIST (type (cdr lst))) (eq 'STR (type (car lst))) (not (is_array lst)))
)

(defun is_array (lst / res)
    (eq (QUOTE <ARRAY>) (car lst))
)

(defun read_list (lst json state / )
   
    (foreach lst_element lst
      ; (princ "---------------------------------------------------------\n")
      ; (princ "IN state    -> ") (princ state) (princ "\n")
      ; (princ "lst_element -> ") (princ lst_element) (princ "\n")
      
      (if (eq 'LIST (type lst_element)) ; Set of data
      (progn
          ; (princ "Is LIST")(princ "\n")
          (cond
            ; ARRAY -> Read any value (Objects, Arrays, strings, numbers, 'true, 'false, 'null)
            ((is_array lst_element)
            ; (princ "-> INIT ARRAY.") (princ "\n")
            (setq reading_val nil)
            (setq json (strcat json "["))
            (setq json (read_list lst_element json 'ARRAY))
            (setq json (strcat json "],"))
            )

            ; ATTRIBUTES IN AN OBJECT
            ((is_attribute_complex lst_element)
            ; (princ "-> ATTRIBUTE COMPLEX IN AN OBJECT.") (princ "\n")
            (setq reading_val nil)
            ; (princ "-> ATTRIBUTE complex.") (princ "\n")
            (setq json (strcat json (value_to_string (car lst_element)) ":"))
            (setq json (read_list (cdr lst_element) json 'OBJECT))
            )
            
            ((is_attribute_simple lst_element)
            (setq reading_val nil)
            ; (princ "-> ATTRIBUTE simple.") (princ "\n")
            (setq json
                (strcat
                  json
                  (value_to_string (car lst_element)) ":"
                  (value_to_string (cdr lst_element)) ","
                )
            )
            )
            
            ; NO ARRAY / NO ATTRIBUTE -> Read Object
            (T
            ; (princ "-> INIT OBJECT.") (princ "\n")
            (setq reading_val nil)
            (setq json (strcat json "{"))
            (setq json (read_list lst_element json 'OBJECT))
            (setq json (strcat json "},"))
            )
          )
      )
      (progn ;not is list / is name or value
          ; (princ "not is list / is name or value.") (princ "\n")
          (if (not (or (eq lst_element '<ARRAY>) (eq lst_element '</ARRAY>)))
            (cond
            ((eq state 'ARRAY)
                (setq json (strcat json (value_to_string lst_element) ","))
            )
            ((eq state 'ATTRIB)
                (if reading_val
                  (progn
                  (setq json (strcat json (value_to_string lst_element) ","))
                  (setq reading_val nil)
                  )
                  (progn
                  (setq json (strcat json (value_to_string lst_element) ":"))
                  (setq reading_val T)
                  )
                )
            )
            ((eq state 'OBJECT)
            )
            )
          )
      )
      )
      ; (princ "OUT state   -> ") (princ state) (princ "\n")
      ; (princ "JSON      -> ") (princ json) (princ "\n")
      ; (princ "---------------------------------------------------------\n")
    )

    json
)

(if (is_array lst)
    (progn
      (setq init_state 'ARRAY)
      (setq init_string "[")
    )
    (progn
      (setq init_state 'OBJECT)
      (setq init_string "{")
    )
)

(setq json (read_list lst init_string init_state))

(if (eq "[" init_string)
    (setq json (strcat json "]"))
    (setq json (strcat json "}"))
)

;Clean the string
(setq json (dmc:json:str_replace json ",}" "}"))
(setq json (dmc:json:str_replace json ",]" "]"))
)

;*************************************************************************************************
;* FIN json_util.lsp
;*************************************************************************************************

20060510412 发表于 2022-11-2 10:05:51

landsat99 发表于 2022-4-24 11:03
Github另一位小哥的 Alisp-Json的读写函数。

The functions included in json_util.lsp:


这个list转json的程序,出来的结果不对啊。
例如((1)(2)(3)),转出来是{{}{}{}},
字符都没有了
页: [1]
查看完整版本: 请问,Autolisp/Visuallisp有读写Json格式的API吗?