sharplispers / cl-json

Json encoder and decoder for Common-Lisp
Other
9 stars 5 forks source link

CLOS #13

Open cage2 opened 1 year ago

cage2 commented 1 year ago

Hi!

The CLOS decoder seems does not works anymore, even the code in the documentation:


(json:with-decoder-simple-clos-semantics
  (let ((json:*json-symbols-package* nil))
    (let ((x (json:decode-json-from-string
               "{\"foo\": [1, 2, 3], \"bar\": true,
                 \"baz\": \"!\"}")))
      (with-slots (foo bar baz) x
        (values x foo bar baz)))))

signals an error:

SB-MOP:CLASS-SLOTS called on #<JSON:FLUID-CLASS JSON:FLUID-OBJECT>, which is not yet finalized.

Bye! C.

bmiww commented 10 months ago

Interestingly enough - if you remove the with-decoder line - run the code once, and add it back in, it starts to work :)

So far - that's my excuse for not attempting to give it a fix.

cage2 commented 10 months ago

Hi!

Interestingly enough - if you remove the with-decoder line - run the code once, and add it back in, it starts to work :)

I tried too, and can confirm the behavior, this is kind of crazy!

So far - that's my excuse for not attempting to give it a fix.

I think i can understand you! :smile:

Bye! C.

cage2 commented 10 months ago

Hi!

Seems that adding

 (progn
    (mapcar #'finalize-inheritance superclasses) ; added this form
    (make-instance 'fluid-class ...))

here, solves the issue; but because, unfortunately, I know near nothing about MOP, i do not think would be a good idea to suggest this code as a proper patch. Any MOP expert wold wants to help?

Bye! C.

bmiww commented 10 months ago

You picked my interest, and I started digging around and reading up on MOP. Also not an expert, but this MR (#15) is what i came up with.

As far as i could tell - your solution wouldn't be too bad either, might run an extra time or two (depending on how many classes you've got) in case if custom classes are involved i'm guessing.

And that said i haven't yet checked how my change works with custom classes. (Learned that this package provides a way to have custom classes - i possibly don't have to have a big blob class which describes all possible json keys i am using)

Gonna play around a bit more. Also not sure how active the maintainers are and if the MR will even be considered.

Anyhow - thanks for the fix @cage2 :) Now i wont have to do weird hacks every time i restart my program.

cage2 commented 10 months ago

Hi @bmiww !

Your solution is better than mine, my code was just a crude hack and nothing more.

And that said i haven't yet checked how my change works with custom classes. (Learned that this package provides a way to have custom classes - i possibly don't have to have a big blob class which describes all possible json keys i am using)

I made a quick test and seems to works just fine!

(defpackage :json-clos
  (:use :cl
        :cl-json)
  (:export :main))

(in-package :json-clos)

(defclass test-class ()
  ((foo
    :initform 'foo
    :initarg  :foo
    :accessor foo)
   (bar
    :initform 'bar
    :initarg  :bar
    :accessor bar)
   (baz
    :initform 'baz
    :initarg  :baz
    :accessor baz)))

(defmethod print-object ((object test-class) stream)
  (print-unreadable-object (object stream)
    (format t "foo: ~s bar: ~s baz: ~s" (foo object) (bar object) (baz object))))

(defun main ()
  (json:with-decoder-simple-clos-semantics
    (let ((instance (json:decode-json-from-string
                     "{\"foo\": [1, 2, 3], \"bar\": true, \"baz\": \"!\",
              \"prototype\": {\"lispPackage\": \"jsonClos\",
                              \"lispClass\": \"test-class\"}}")))
      (format t "~a → ~a~%" (class-of instance) instance))))

Anyhow - thanks for the fix @cage2 :)

You're welcome! Thanks to you to make me remember this report, I learnt something about MOP too!

I hope someone will merge your patch soon!

Bye! C.