Декодировать в clojure, JSON, clojure.data.json & cheshire.core, не может пользовательское декодирование с чеширом
Мой проект анализирует JSON с библиотекой чтения / записи, которая называется:
У меня были проблемы, я пытался заставить работать декодер (func), поэтому я начал возиться с:
Мой JSON содержит данные, которые состоят из поля с именем "зона", в котором содержится вектор с ключами: внутри, например: {:zone: [:hand:table]}, который хранится в строках внутри вектора, хранящегося следующим образом: {"zone": ["hand" "table"]}
Итак, я выяснил, как преобразовать пример данных, используя:
(mapv keyword {"zone" : ["hand"]})
это было здорово, мне тогда нужно было выяснить, как реализовать декодер для cheshire, я не мог сделать это с моей логикой, я потратил на это всего час, но я использовал data.json и декодер Функция относительно проста, я думаю.
Я получил свой проект на работу, вот пример кода:
(ns clojure-noob.core (:require
[cheshire.core :refer [decode]]
[clojure.data.json :as j-data]
) (:gen-class))
(defn -main
"I don't do a whole lot ... yet."
[& args]
)
это использует Чешир:
(let [init (decode "{\"zone\" : [\"hand\"]}" true
(fn [field-name]
(if (= field-name "zone")
(mapv keyword [])
[])))]
(println (str init)))
это использует data.json:
(defn my-value-reader [key value]
(if (= key :zone)
(mapv keyword value)
value))
(let [init (j-data/read-str
"{\"zone\" : [\"hand\"]}"
:value-fn my-value-reader
:key-fn keyword)]
(println (str init)))
Я хочу нижний результат этих двух из консоли:
{:zone ["hand"]}
{:zone [:hand]}
Проблема в том, что я хотел бы сделать это с помощью cheshire ps. Я читаю заводской раздел cheshire? может это проще?
2 ответа
Я бы согласился с @TaylorWood. Не связывайтесь с декодером, просто перекусите. Во-первых, разбор JSON. Во-вторых, преобразовать результат.
(def data "{\"zone\" : [\"hand\"]}")
(-> data
(cheshire.core/decode true)
(update-in ["zone"] (partial mapv keyword)))
#=> {:zone [:hand]}
Я рекомендую вам использовать такой инструмент, как schema.tools
чтобы принудить ввод. Вы можете добавить второй проход, который пытается привести строки JSON в более богатые типы замыкания.
Вот пример кода!
;; require all the dependencies. See links below for libraries you need to add
(require '[cheshire.core :as json])
(require '[schema.core :as s])
(require '[schema.coerce :as sc])
(require '[schema-tools.core :as st])
;; your data (as before)
(def data "{\"zone\" : [\"hand\"]}")
;; a schema that wants an array of keywords
(s/defschema MyData {:zone [s/Keyword]})
;; use `select-schema` along with a JSON coercion matcher
(-> data
(json/decode true)
(st/select-schema MyData sc/json-coercion-matcher))
;; output: {:zone [:hand]}
С помощью defschema
определение формы данных, которые вы хотите, дает вам общее решение для сериализации в JSON, в то же время получая все преимущества типов значений Clojure. Вместо того, чтобы явно "выполнять" работу по преобразованию, ваша схема описывает ожидаемый результат, и, надеюсь, принуждение может сделать правильную вещь!
Ссылки на библиотеки: - https://github.com/plumatic/schema- https://github.com/metosin/schema-tools
Примечание: вы можете сделать то же самое с clojure.spec, используя https://github.com/metosin/spec-tools. Проверьте их readme для некоторой помощи.