Декодировать в clojure, JSON, clojure.data.json & cheshire.core, не может пользовательское декодирование с / cheshire - PullRequest
0 голосов
/ 11 сентября 2018

Мой проект анализирует JSON с библиотекой чтения / записи, которая называется:

cheshire.core

У меня возникли проблемы при попытке получить декодирование (функция), поэтому я начал возиться с:

data.json

Мой JSON содержит данные, которые состоят из поля с именем "зона", который содержит вектор с: ключи внутри, вот так {: зона: [: рука: таблица]}, которая хранится в строках внутри вектора, который хранится так: {"зона": ["рука" "таблица"]}

ИтакЯ выяснил, как преобразовать пример данных, используя:

(mapv keyword {"zone" : ["hand"]})

, что было здорово, тогда мне нужно было выяснить, как реализовать декодер для Чешира, я не мог сделать это с помощью своей логики, я толькопотратил на это около часа, но я использовал 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 ]

0 голосов
/ 13 сентября 2018

Я рекомендую использовать инструмент типа schema.tools для принудительного ввода.Вы можете добавить второй проход, который попытается привести строки JSON в более богатые типы clojure.

Вот пример кода!

;; 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#coercion

Примечание: вы можете сделать то же самое с clojure.spec, используя metosin / spec-tools .Проверьте их readme для некоторой помощи.

0 голосов
/ 11 сентября 2018

Я бы согласился с @TaylorWood.Не связывайтесь с декодером, просто перекусите.Во-первых, разбор JSON.Во-вторых, преобразовать результат.

(def data "{\"zone\" : [\"hand\"]}")

(-> data 
    (cheshire.core/decode true)
    (update-in ["zone"] (partial mapv keyword)))
#=> {:zone [:hand]}
...