Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add scm->value and value->scm specifications to define-json-type #82

Open
vintnes opened this issue Mar 26, 2023 · 2 comments
Open

Add scm->value and value->scm specifications to define-json-type #82

vintnes opened this issue Mar 26, 2023 · 2 comments

Comments

@vintnes
Copy link

vintnes commented Mar 26, 2023

Hi Aleix. Thank you for this solid library I use daily.

It's kind of painful when a JSON type with a nested record type needs to implement some value conversion.

Example

(use-modules (json))

(define simplified-real-world-json
"{\"initializationDate\":\"2018-06-19T08:13:04.29+02:00\",\"product\":\"ICE\",\"trainNumber\":\"369\",\"serviceId\":\"1529131014\",\"wagons\":[{\"group\":0,\"type\":\"TRIEBKOPF\",\"id\":\"938054015830\",\"wagonNumber\":null,\"status\":\"OFFEN\"}]}")

(define-json-type <manifest>
  (initialization-date "initializationDate")
  (product)
  (train-number "trainNumber")
  (service-id "serviceId")
  (wagons "wagons" #(<wagon>)))

(define-json-type <wagon>
  (group) (type) (id) (number "wagonNumber") (status))

Now let's say we'd like to operate on the train number (simpler than the date for illustration purposes), delivered to us by the grace of German engineering in string format. Reformatting according to define-json-mapping is a little tedious but overall worth the convenience/granularity tradeoff in my opinion. The painful part is that we also have to manually map any nested records, which isn't related to the problem we're working on.

(use-modules (ice-9 match))

(define wagon-converter
  (match-lambda (#((= scm->wagon wagons) ...) wagons)
                (((= wagon->scm wagons) ...) (list->vector wagons))))

(define-json-mapping <manifest> manifest manifest?
  json->manifest <=> manifest->json
  (initialization-date manifest-initialization-date "initializationDate")
  (product manifest-product)
  (train-number manifest-train-number "trainNumber" string->number number->string)
  (service-id manifest-service-id "serviceId")
  (wagons manifest-wagons "wagons" wagon-converter wagon-converter))

(call-with-input-string simplified-real-world-json json->manifest)

Am I just missing something simple? Is there any reason why define-json-type can't support the scm->value and value->scm field specifications? Have you considered using keywords over positional parameters, or would you be open to that change in the future? Thanks again for your support.

@aconchillo
Copy link
Owner

hi @vintnes ! Yes, it's definitely a little bit more painful. I added define-json-type to be able to define simple JSON objects in a very simple way, but when it comes to flexibility you run into the issue you are having now. It might be worth adding keyword arguments there as you suggest, for example:

(define-json-type <manifest>
  (initialization-date "initializationDate")
  (product)
  (train-number "trainNumber" #:encode number->string #:decode string->number)
  (service-id "serviceId")
  (wagons "wagons" #(<wagon>)))

@aconchillo
Copy link
Owner

I don't have much time lately but I think it would be a nice addition. I'll see if I find some time soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants