I'm new to Clojure and I have a problem that I really can't find a solution to.
I have a structure already defined with Clojure Spec, its keys and data types match with a JSON file.
Doing an inspection I get the error I appreciate your help
Spec File
(ns invoice-spec
(:require
[clojure.spec.alpha :as s] ))
(s/def :customer/name string?)
(s/def :customer/email string?)
(s/def :invoice/customer (s/keys :req-un [:customer/name
:customer/email]))
;(s/def :tax/tax_category #{:IVA})
(s/def :tax/tax_category string?)
(s/def :tax/tax_rate int?)
(s/def ::tax (s/keys :req-un [:tax/tax_category
:tax/tax_rate]))
(s/def :invoice-item/taxes (s/coll-of ::tax :kind vector? :min-count 1))
(s/def :invoice-item/price double?)
(s/def :invoice-item/quantity double?)
(s/def :invoice-item/sku string?)
(s/def ::invoice-item
(s/keys :req-un [:invoice-item/price
:invoice-item/quantity
:invoice-item/sku
:invoice-item/taxes]))
;(s/def :invoice/issue_date inst?)
(s/def :invoice/issue_date string?)
(s/def :invoice/items (s/coll-of ::invoice-item :kind vector? :min-count 1))
(s/def ::invoice
(s/keys :req-un [:invoice/issue_date
:invoice/customer
:invoice/items]))
Clj File
(defn invoice
[name_json]
(json/read (clojure.java.io/reader name_json) :key-fn keyword))
Validation
(s/valid? ::invoice/invoice (invoice "invoice.json"))
=> false
View Errors
(expound/expound ::invoice/invoice (invoice "invoice.json"))
-- Spec failed --------------------
{:invoice
{:payment_means_type "DEBITO",
:order_reference "PEDID_0001",
:number "1",
:issue_date "13/10/2020",
:payment_date "12/11/2020",
:customer
{:name "ANDRADE RODRIGUEZ MANUEL ALEJANDRO",
:email "[email protected]"},
:payment_means "DEBIT_CARD",
:items
[{:price 10000.0,
:quantity 1.0,
:sku "SUPER-1",
:taxes [{:tax_category "IVA", :tax_rate 5}]}
{:price 20000.0,
:quantity 1.0,
:sku "SUPER-2",
:taxes [{:tax_category "IVA", :tax_rate 19}]}
{:price 30000.0,
:quantity 1.0,
:sku "SUPER-3",
:taxes [{:tax_category "IVA", :tax_rate 19}]}],
:retentions
[{:tax_category "RET_FUENTE", :tax_rate 15.0}
{:tax_category "RET_IVA", :tax_rate 15.0}]}}
should contain keys: :customer, :issue_date, :items
| key | spec |
|=============+==============================================|
| :customer | (keys :req [:customer/name :customer/email]) |
|-------------+----------------------------------------------|
| :issue_date | string? |
|-------------+----------------------------------------------|
| :items | (coll-of |
| | :invoice-spec/invoice-item |
| | :min-count |
| | 1 |
| | :kind |
| | vector?) |
-- Relevant specs -------
:invoice-spec/invoice:
(clojure.spec.alpha/keys
:req-un
[:invoice/issue_date :invoice/customer :invoice/items])
-------------------------
Detected 1 error
=> nil
JSON File
{
"invoice": {
"issue_date": "13/10/2020",
"order_reference": "PEDID_0001",
"payment_date": "12/11/2020",
"payment_means": "DEBIT_CARD",
"payment_means_type": "DEBITO",
"number": "1",
"customer": {
"name": "ANDRADE RODRIGUEZ MANUEL ALEJANDRO",
"email": "[email protected]"
},
"items": [
{
"price": 10000.00,
"quantity": 1.00,
"sku": "SUPER-1",
"taxes": [
{
"tax_category": "IVA",
"tax_rate": 5
}
]
},
{
"price": 20000.00,
"quantity": 1.00,
"sku": "SUPER-2",
"taxes": [
{
"tax_category": "IVA",
"tax_rate": 19
}
]
},
{
"price": 30000.00,
"quantity": 1.00,
"sku": "SUPER-3",
"taxes": [
{
"tax_category": "IVA",
"tax_rate": 19
}
]
}
],
"retentions": [
{
"tax_category": "RET_FUENTE",
"tax_rate": 15.00
},
{
"tax_category": "RET_IVA",
"tax_rate": 15.0
}
]
}
}
My goal is to obtain the following result
(s/valid? ::invoice/invoice (invoice "invoice.json"))
=> true
You have main keyword
:invoice
, so you need one mores/def
, I called::data
Without that
def
, you must get value of:invoice
, which is the map with keysissue_date
,customer
anditems
: