0

我想在我的数据库中插入大量 JSON 数据。

[{
    "term": "wine",
    "name": "Bubba Wine & Spirits",
    "address": "1234 N San Fake Rd,"
}, {
    "term": "wine",
    "name": "Wine Shop",
    "address": "123 N Not Real Blvd,"
}]

cl-json用来转换为 lisp 对象。

(defvar *data*
  (decode-json (open "my-json-file.json")))

结果如下所示:

(((:TERM . "wine") (:NAME . "Bubba Wine & Spirits")
  (:ADDRESS . "1234 N San Fake Rd,"))
 ((:TERM . "wine") (:NAME . "Wine Shop")
  (:ADDRESS . "123 N Not Real Blvd,")))

Postmodern列出了一种在insert-rows-into此处插入多行的方法:https ://sites.google.com/site/sabraonthehill/postmodern-examples/postmodern-insert#multiple-row-inserts

(:insert-rows-into 'table :columns 'a 'b :values '((10 20) (30 40)))

它不是默认的 JSON 格式。

看起来我有两个选择:

  1. 按摩数据以适应
  2. 找到一个按原样处理的函数。

我怀疑:insert-rows-into做了我想要的,但我不太确定如何把它塞进去。

4

2 回答 2

4

这有帮助吗?

(defun compose (&rest fns)
  (lambda (x)
    (reduce #'funcall fns :initial-value x :from-end t)))

(defun quotify (x)
  `',x)

(defun guess-columns (data *package*)
  (mapcar (compose #'quotify #'intern #'symbol-name #'first) (first data)))

(defun guess-values (data)
  (loop for x in data collect (mapcar #'cdr x)))

(defun insert-rows (data package)
  `(:insert-rows-into 'table :columns ,@(guess-columns data package)
                  :values ',(guess-values data)))

insert-rows用你的电话*data*给结果

(:INSERT-ROWS-INTO 'TABLE :COLUMNS 'TERM 'NAME 'ADDRESS :VALUES
 '(("wine" "Bubba Wine & Spirits" "1234 N San Fake Rd,")
   ("wine" "Wine Shop" "123 N Not Real Blvd,")))
于 2013-11-07T06:19:12.957 回答
1

您可以修改解析器的行为以生成所需的输出,应该这样做:

(defun json->insert ()
  (labels ((%string->symbol (s) (intern (string-upcase s))))
    (let (keys values row)
      (json:bind-custom-vars
          (:object-key
           (lambda (key)
             (unless (member key keys :test #'equal)
               (push key keys)))
           :object-value
           (lambda (value) (push value row))
           :end-of-object
           (lambda () (setf values (cons row values) row nil)))
        (json:decode-json-from-string
         "[{
    \"term\": \"wine\",
    \"name\": \"Bubba Wine & Spirits\",
    \"address\": \"1234 N San Fake Rd,\"
    }, {
    \"term\": \"wine\",
    \"name\": \"Wine Shop\",
    \"address\": \"123 N Not Real Blvd,\"
    }]"))
      (list (mapcar #'%string->symbol keys) values))))

;; (json->insert)
;; ((ADDRESS NAME TERM)
;;  (("123 N Not Real Blvd," "Wine Shop" "wine")
;;   ("1234 N San Fake Rd," "Bubba Wine & Spirits" "wine")))

但是,在我看来,这cl-json是过度设计的,您可能会使用诸如cl-yacc构建临时解析器之类的东西做得更好并完成它。我知道建议重新发明某些东西是一件很奇怪的事情,尤其是当已经有了一个工具时,但这就是我最终在某个时候做的事情(我需要一个拉式解析器)。但我鼓励你运用自己的判断。

于 2013-11-07T15:49:22.963 回答