Это поможет прояснить, что происходит. Начнем с добавления полезной библиотеки:
(ns tst.demo.core
(:use tupelo.core tupelo.test)
(:require
[tupelo.core :as t]
[tupelo.string :as str]
))
Чтобы избежать двусмысленности двойных кавычек как для буквальной строки, так и для встроенной внутри строки, мы записываем исходный JSON с использованием одинарных кавычек, а затем используем вспомогательную функцию str/quotes->double
для преобразования каждой одинарной кавычки в строке в двойную. Цитировать. В противном случае мы могли бы прочитать исходный JSON из файла (вместо того, чтобы иметь его встроенным).
(def json-str
(str/quotes->double
"{
'Data': [
{
'Metadata': {
'Series': '1/2'
},
'Hybrid': {
'Foo': 76308,
'Bar': '76308',
'Cat': 'Foo123'
}
}
],
'Footer': {
'Count': 3,
'Age': 0
}
} "))
Сначала мы преобразуем строку json в структуру данных EDN (а не строку). Затем мы преобразуем структуру данных EDN в строку EDN. Вывод (как println
, так и prn
) иллюстрирует различия:
(dotest
(let [edn-data (t/json->edn json-str) ; JSON string => EDN data
edn-str (pr-str edn-data) ; EDN data => EDN string
]
(newline)
(println "edn-data =>")
(spy-pretty edn-data) ; uses 'prn'
(newline)
(println "edn-str (println) =>")
(println edn-str)
(newline)
(println "edn-str (prn) =>")
(prn edn-str)))
с результатом:
------------------------------------------
Clojure 1.10.2-alpha1 Java 14.0.1
------------------------------------------
Testing tst.demo.core
edn-data =>
{:Data
[{:Metadata {:Series "1/2"},
:Hybrid {:Foo 76308, :Bar "76308", :Cat "Foo123"}}],
:Footer {:Count 3, :Age 0}}
edn-str (println) =>
{:Data [{:Metadata {:Series "1/2"}, :Hybrid {:Foo 76308, :Bar "76308", :Cat "Foo123"}}], :Footer {:Count 3, :Age 0}}
edn-str (prn) =>
"{:Data [{:Metadata {:Series \"1/2\"}, :Hybrid {:Foo 76308, :Bar \"76308\", :Cat \"Foo123\"}}], :Footer {:Count 3, :Age 0}}"
Тщательно продумайте, что такое структура данных, а что - строка. Если мы напишем [1 :b "hi"]
в исходном файле Clojure, Clojure Reader создаст структуру данных, которая представляет собой трехэлементный вектор, содержащий int, ключевое слово и строку. Если мы преобразуем это в строку с помощью str
, на выходе будет строка из 11 символов, а не структура данных.
Однако, если мы хотим вставить эту строку (внутри двойных кавычек) в наш исходный файл, нам нужны не только внешние двойные кавычки для обозначения начала и конца строки, но и каждая двойная кавычка внутри строки (например, как часть "hi"
) должны быть экранированы, чтобы Clojure Reader мог сказать, что они принадлежат внутри строки, и не отмечают начало или конец строки.
Чтобы привыкнуть ко всем режимам, нужно время!
Clojure Reader против компилятора
Файлы исходного кода Clojure обрабатываются за 2 прохода.
Clojure Reader берет текст каждого исходного файла (гигантскую строку из многих строк) и преобразует его в структуру данных.
Компилятор Clojure берет структуру данных из (1) и выводит байт-код Java.
person
Alan Thompson
schedule
16.07.2020