Конвертировать yaml -> json в ракетку - PullRequest
1 голос
/ 27 января 2020

Я хотел преобразовать некоторые документы yaml в json, используя Racket и библиотеки yaml и json. Оба, кажется, работают очень хорошо, но не обязательно работают вместе. С риском, что этот вопрос будет немного мета (меня интересует идиоматическое c решение), может ли кто-нибудь указать мне правильное направление?

Пример yaml:

Title: Example
Description: An example
Content:
  Type1:
    - foo
    - bar
    - baz
  Type2:
    - chocolate
    - vanilla
    - strawberry

Моя быстрая попытка конвертировать yaml:

#lang racket/base

(require json
         yaml)

; reading is easy
(define example-yaml (file->yaml  "./example.yaml"))

; writing doesn't like the keys-as-strings... why not?
; (write-json example-yaml)
; write-json: expected argument of type <legal JSON key value>; given: "Description"

; keys-as-symbols seems to be fine
(define example-yaml-2
  #hash((Content
         .
         #hash((Type1 . ("foo" "bar" "baz"))
               (Type2 . ("chocolate" "vanilla" "strawberry"))))
        (Description . "An example")
        (Title . "Example")))

(write-json example-yaml-2)
; {"Content":{"Type2":["chocolate","vanilla","strawberry"],"Type1":["foo","bar","baz"]},"Description":"An example","Title":"Example"}

Я понял, что проблема в том, что пакет json не видит строки как допустимый ключ в jsexpr. Документы дают следующий пример:

> (jsexpr? #hasheq(("turnip" . 82)))

#f

С того места, где я сижу, параметры выглядят следующим образом:

  1. Измените поведение пакета yaml для генерации ключи как символы, а не как строки
  2. Измените поведение пакета json, чтобы трактовать (jsexpr? #hasheq(("turnip" . 82))) как #t
  3. Разобрать мои yamls, а затем обработать полученную структуру данных так, чтобы ключи являются символами.

Полагаю, я не до конца понимаю последствия (или у меня есть solid дескриптор реализации) этих опций. Я также не совсем уверен, почему ключи как строки не являются допустимыми jsexprs, учитывая, что json, который он излучает, также использует строки в качестве ключей. Спасибо за любую информацию, которую вы можете предоставить!

1 Ответ

2 голосов
/ 27 января 2020

Для метода 3 простого изменения ключей * ha-1033 * из строк в символы может быть недостаточно. Это зависит от того, сколько вы знаете о формате ваших данных.

Например, пакет yaml допускает все виды вещей в качестве «ключей», не только строки, но и двоичные данные, числа, га sh -maps или любые другие объекты Yaml (ключи могут быть произвольными узлами).

Поэтому вы должны либо:

  1. Заранее знать, что все ключи во всех ваших данных Yaml просты strings,
  2. Или можно разумно преобразовать любое произвольное значение Yaml в символ,
  3. Или преобразовать карты Yaml в некоторую Json структуру, отличную от Json map.

Пока я собираюсь предположить (1), что вы заранее знаете, что все ключи являются строками.

;; yaml-key->symbol
;; In my Yaml data, I know beforehand that all keys are strings
(define (yaml-key->symbol key)
  (cond
    [(string? key) (string->symbol key)]
    [else
     (error 'yaml-key->symbol
            "expected all Yaml keys to be strings, but got: ~v"
            key)]))

Существуют другие потенциальные несоответствия между Yaml и Json, которые вы могли бы нужно учитывать.

  • Как конвертировать байтовые строки yaml? Как списки байтов? Шестнадцатеричные строки?
  • Как конвертировать наборы yaml? Как списки?
  • Как конвертировать временные метки / даты yaml? Как Json отображает поля отображения на числа? Дата строки? Количество секунд, прошедшее с эпохи unix?

. По каждому из этих вопросов примите решение и задокументируйте его. Или, если вы заранее знаете, что ваши данные Yaml определенно не содержат ни одного из них, запишите это тоже и подтвердите с ошибкой, аналогичной yaml-key->symbol выше.

Как только вы знаете, как конвертировать все, что вы Вы можете увидеть в ваших данных рекурсивный обход Yaml и преобразовать его в Json.

...