5a32a34392a2

Refactor a couple of things

Changes the `:json/class` initarg to just `:json` because it's used so much.
Seems more ergonomic.

Also changes slots without an explicit `:json` to just be standard slots and to
not be serialized.  This seems safer and more reasonable anyway — I'd rather
have to be a little more explict that to accidentally serialize a `password`
slot.
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Tue, 28 Jul 2020 21:28:29 -0400
parents e3c35d5a9681
children 3dbd9b45cf55
branches/tags (none)
files src/main.lisp

Changes

--- a/src/main.lisp	Wed Jul 22 20:17:30 2020 -0400
+++ b/src/main.lisp	Tue Jul 28 21:28:29 2020 -0400
@@ -272,35 +272,47 @@
 
 
 (defclass json-direct-slot-definition (c2mop:standard-direct-slot-definition)
-  ((json-name :initarg :json/name :accessor json-name)
-   (json-class :initarg :json/class :accessor json-class)))
+  ((json-class :initarg :json :accessor json-class)
+   (json-name :initarg :json/name :accessor json-name)))
 
 (defclass json-effective-slot-definition (c2mop:standard-effective-slot-definition)
-  ((json-name :initarg :json/name :accessor json-name)
-   (json-class :initarg :json/class :accessor json-class)
+  ((json-class :initarg :json :accessor json-class)
+   (json-name :initarg :json/name :accessor json-name)
    (json-initarg :accessor json-initarg)))
 
 (defmethod c2mop:direct-slot-definition-class ((class json-class) &rest initargs)
-  (declare (ignore initargs))
-  (find-class 'json-direct-slot-definition))
+  (if (getf initargs :json)
+    (find-class 'json-direct-slot-definition)
+    (call-next-method)))
+
+(defvar *effective-slot-definition-class* nil)
 
 (defmethod c2mop:effective-slot-definition-class ((class json-class) &rest initargs)
   (declare (ignore initargs))
-  (find-class 'json-effective-slot-definition))
+  ;; I'm not sure why we need to use this hack here, but for some reason
+  ;; initargs doesn't contain the slot options like :json and :json/name here
+  ;; like it does in direct-slot-definition-class.  So we need another way to
+  ;; know which class to use here.
+  (or *effective-slot-definition-class* (call-next-method)))
 
 (defmethod c2mop:compute-effective-slot-definition ((class json-class) name direct-slots)
-  (let ((eslot (call-next-method))
-        (dslot (first direct-slots)) ; todo be smarter about coalescing these 
-        (initarg (gensym (format nil "json-initarg-~A" name)))) ; todo nicer name
-    (setf (json-name eslot) (if (slot-boundp dslot 'json-name)
-                              (json-name dslot)
-                              (funcall (slot-name-to-json-name class) name)) ; todo make this less shitty
-          (json-class eslot) (if (slot-boundp dslot 'json-class)
-                               (canonicalize-class-designator (json-class dslot))
-                               '(t))
-          (json-initarg eslot) initarg) ; todo nicer name
-    (push initarg (c2mop:slot-definition-initargs eslot))
-    eslot))
+  (if (not (some (lambda (dslot)
+                   (typep dslot 'json-direct-slot-definition))
+                 direct-slots))
+    (call-next-method)
+    (let* ((*effective-slot-definition-class* (find-class 'json-effective-slot-definition))
+           (eslot (call-next-method))
+           (dslot (first direct-slots)) ; todo be smarter about coalescing these
+           (initarg (gensym (format nil "json-initarg-~A" name)))) ; todo nicer name
+      (setf (json-name eslot) (if (slot-boundp dslot 'json-name)
+                                (json-name dslot)
+                                (funcall (slot-name-to-json-name class) name)) ; todo make this less shitty
+            (json-class eslot) (if (slot-boundp dslot 'json-class)
+                                 (canonicalize-class-designator (json-class dslot))
+                                 '(t))
+            (json-initarg eslot) initarg) ; todo nicer name
+      (push initarg (c2mop:slot-definition-initargs eslot))
+      eslot)))
 
 
 (defun json-slots (class)
@@ -308,6 +320,11 @@
                  (c2mop:class-slots class)))
 
 (defun make-name-initarg-map (class)
+  "Return a name/initarg map for the JSON slots of `class`.
+
+  The result will be a hash table of `{name: (initarg class contained-class)}`.
+
+  "
   (let* ((slots (json-slots class))
          (result (make-hash-table :test #'equal :size (length slots))))
     (dolist (slot slots)
@@ -508,46 +525,3 @@
       (null (with-output-to-string (s)
               (print% object s))))))
 
-
-#; Scratch --------------------------------------------------------------------
-
-(defclass a () ())
-(defclass b () ())
-(defclass c () ())
-(defclass d () ())
-
-(defclass post (a b c)
-  ((id :json/class number)
-   (title :json/class string)
-   (body :json/class string)
-   (author :json/class user)
-   (extra))
-  (:metaclass json-class)
-  (:unknown-slots :discard))
-
-(defclass user ()
-  ((id :json/class number :initarg :id)
-   (name :json/class string)
-   (friends :json/class (vector number)))
-  (:metaclass json-class))
-
-
-(find-class 'user)
-(find-class 'post)
-(find-class 'wat)
-
-(make-instance 'user :id 1)
-(make-instance 'post)
-
-(setf (find-class 'post) nil (find-class 'user) nil)
-
-(print (read '(vector post) (substitute #\" #\' "[{
-    'id': 69,
-    'body': 'oh my christ, it works!',
-    'author': {
-        'id': 101,
-        'name': 'sjl',
-        'friends': [1,2,3]
-    },
-    'wat': 1
-  }]")))