You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将树形结构数据库数据转为单块JSON键值对(无额外库)

问题描述

我的数据库返回如下树形结构数据:

'((7 "vince" "vince1@test.com" "space" "no value" 1)
  (8 "vince" "vince2@test.com" "place" "no value" 1)
  (9 "Smith" "Smith@gmail.com" "now" "no value" 1))

其中第二列为名字,第三列为邮箱。我希望将其转换为包含所有记录的单个JSON数组,但尝试的方法只返回多个独立的JSON块,遇到了困难。

我已尝试的方法:

  1. 编写函数提取单个列表项中的姓名和邮箱:
(defun get-name-&-emails-db1 (lst)
  (if (null lst)
      nil
      (let* ((name (second lst))
             (email (third lst)))
    (cl-json:encode-json-to-string `((:name . ,name)(:email . ,email))))))
  1. 遍历数据集:
(mapcar #'get-name-&-emails-db1 (return-data-tree))

现在需要解决的是:如何生成包含所有记录的单个JSON块,优先希望不使用任何额外库实现。

解决方案

你现在的问题出在:mapcar会给每个列表项单独调用JSON编码函数,所以得到的是一堆独立的JSON字符串,而不是把所有记录合并成一个完整的JSON数组。

方法一:不依赖第三方库实现

直接手动拼接JSON字符串就行,步骤很简单:

  1. 遍历所有数据,把每个条目的姓名、邮箱转换成{"name": "...", "email": "..."}格式的字符串;
  2. 把这些字符串用逗号连起来,再套上数组的[]括号。

代码实现:

(defun data-to-json (data)
  (let ((entries (mapcar (lambda (item)
                           (format nil "{\"name\": \"~a\", \"email\": \"~a\"}"
                                   (second item)
                                   (third item)))
                         data)))
    (format nil "[~{~a~^, ~}]" entries)))

;; 调用示例
(data-to-json '((7 "vince" "vince1@test.com" "space" "no value" 1)
                (8 "vince" "vince2@test.com" "place" "no value" 1)
                (9 "Smith" "Smith@gmail.com" "now" "no value" 1)))

要是姓名或邮箱里有双引号这类特殊字符,得加个转义处理,不然JSON会报错:

(defun escape-string (s)
  (substitute-if #\\ (lambda (c) (char= c #\")) s))

;; 升级后的转换函数
(defun data-to-json (data)
  (let ((entries (mapcar (lambda (item)
                           (format nil "{\"name\": \"~a\", \"email\": \"~a\"}"
                                   (escape-string (second item))
                                   (escape-string (third item))))
                         data)))
    (format nil "[~{~a~^, ~}]" entries)))

方法二:正确用cl-json库

要是还是想用cl-json,别逐个编码,先把所有数据转成Lisp的嵌套列表,再一次性编码:

(defun get-name-emails (item)
  (list (cons :name (second item))
        (cons :email (third item))))

(defun data-to-json-with-cljson (data)
  (cl-json:encode-json-to-string (mapcar #'get-name-emails data)))

;; 调用示例
(data-to-json-with-cljson (return-data-tree))

这样mapcar会生成一个包含所有键值对列表的大列表,再用encode-json-to-string一次性编码,就能得到单个完整的JSON数组了。

内容的提问来源于stack exchange,提问作者Vinn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 05:45:41