3

From JSON, I'm trying to build a nested list of nodes which should look like the expected result below:

(html (head (meta title)) (body (ul (div) (div) (div))) ; I guess this is the right approach for an interface label

This is the original data from json-read-from-string:

(pp json-dom)
((tag . "html")
 (children .
           [((tag . "head")
             (children .
                       [((tag . "meta")
                         (children .
                                   []))
                        ((tag . "title")
                         (children .
                                   []))]))
            ((tag . "body")
             (children .
                       [((tag . "ul")
                         (children .
                                   [((tag . "div")
                                     (children .
                                               []))
                                    ((tag . "div")
                                     (children .
                                               []))
                                    ((tag . "div")
                                     (children .
                                               []))]))                                               
                        ]))]))

I will be grateful if you can please assist in helping to obtain the correct result.

This is what I have done so far:

Starting with the recursive function, I'm faced with either invalid argument when testing with listp or nil result when testing the top argument with vectorp

(defun sidetree (node) 
  (when (vectorp node) 
    (cons (cdr (assoc 'tag node)) 
          (sidetree 
            (assoc 'children node)
            ; (cdr (car (aref (cdr (assoc 'children json-dom)) 0)))
            ))))

(pp (sidetree json-dom))
nil"nil"

I tried using the letrec approach as well,

(defun fliptree()
  (letrec
      ((untree (lambda (tr)
                  (list
                  (alist-get 'tag tr)
                  (append (apply-partially untree '(alist-get 'children node)) nil )
                  ))))
    (funcall untree json-dom)))

And got the following result. I don't know what I'm not doing right.

(pp (fliptree))
("html"
  (128 "\302\300\303\301\"\"\207"
      [(closure
            ((untree closure #4
                    (tr)
                    (list
                      (alist-get 'tag tr)
                      (append
                      (apply-partially untree
                                        '(alist-get 'children node))
                      nil)))
            t)
            (tr)
          (list
          (alist-get 'tag tr)
          (append
            (apply-partially untree
                            '(alist-get 'children node))
            nil)))
        ((alist-get 'children node))
        apply append]
      6 "\n\n(fn &rest ARGS2)"))
​
​
​
12
  • I have edited the expected result
    – alexander
    Commented Mar 7, 2022 at 7:24
  • The parentheses/brackets in your original data do not seem to be complete, i.e. Emacs indicates that the last parenthesis does not match with the first parenthesis. Are you sure that you posted it correctly? Commented Mar 7, 2022 at 7:56
  • Can you please check again ?
    – alexander
    Commented Mar 7, 2022 at 8:10
  • I mean in the 'output' of (pp json-dom). Commented Mar 7, 2022 at 8:25
  • 1
    Your expected result is still inconsistent. meta and title are not treated the same way as the essentially-identical sequence of three div elements. It's incredibly hard to know what you're trying to achieve when you include such inconsistencies. (If you don't know what you want, how is anyone else supposed to know?)
    – phils
    Commented Mar 7, 2022 at 9:26

1 Answer 1

4

We can get 'more or less' the result that you want using the following function:

(defun json-format (obj)
  (when obj
      (cons (let ((rest (cdr (car obj))))
              (if (vectorp rest)
                  (map 'list #'json-format rest)
                (intern rest)))
            (unless (= (length (cdadr obj)) 0)
              (car (json-format (cdr obj)))))))

Calling it with the data (where data is you 'original data'), (json-format data), returns the following:

(html (head (meta) (title)) (body (ul (div) (div) (div))))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.