Skip to content

Commit 2d004ce

Browse files
Merge pull request #469 from jmglov/json-writer
Add pixie.data.json for reading and writing JSON
2 parents dd5815d + 6b6673d commit 2d004ce

File tree

2 files changed

+117
-0
lines changed

2 files changed

+117
-0
lines changed

pixie/data/json.pxi

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
(ns pixie.data.json
2+
(:require [pixie.parser.json]
3+
[pixie.string :as string]))
4+
5+
(def read-string pixie.parser.json/read-string)
6+
7+
(defprotocol IToJSON
8+
(write-string [this]))
9+
10+
(defn- write-map [m]
11+
(str "{"
12+
(->> m
13+
(transduce (comp (map (fn [[k v]] (string/interp "$(write-string k)$: $(write-string v)$")))
14+
(interpose ", "))
15+
string-builder))
16+
"}"))
17+
18+
(defn- write-sequential [xs]
19+
(str "["
20+
(->> xs
21+
(transduce (comp (map write-string)
22+
(interpose ", "))
23+
string-builder))
24+
"]"))
25+
26+
(defn- write-str [s]
27+
(string/interp "\"$s$\""))
28+
29+
(extend-protocol IToJSON
30+
Character (write-string [this] (write-str this))
31+
Cons (write-string [this] (write-sequential this))
32+
EmptyList (write-string [this] (write-sequential this))
33+
Nil (write-string [_] "null")
34+
Number (write-string [this] (str this))
35+
Keyword (write-string [this] (write-str (name this)))
36+
LazySeq (write-string [this] (write-sequential this))
37+
IMap (write-string [this] (write-map this))
38+
IVector (write-string [this] (write-sequential this))
39+
PersistentList (write-string [this] (write-sequential this))
40+
Ratio (write-string [this] (str (float this)))
41+
String (write-string [this] (write-str this)))
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
(ns pixie.tests.data.test-json
2+
(:require [pixie.test :refer :all]
3+
[pixie.data.json :as json]))
4+
5+
6+
7+
;; This test just ensures that we can use read-string; more thorough testing is
8+
;; done in pixie.tests.parser.test-json
9+
(deftest test-read-string
10+
(assert= (json/read-string "{\"foo\": 42, \"bar\": [\"baz\"]}")
11+
{"foo" 42, "bar" ["baz"]}))
12+
13+
(deftest test-strings
14+
(assert-table [x y] (assert= (json/write-string x) y)
15+
\a "\"a\""
16+
"foo" "\"foo\""
17+
:bar "\"bar\""
18+
"" "\"\""))
19+
20+
(deftest test-numbers
21+
(assert-table [x y] (assert= (json/write-string x) y)
22+
1 "1"
23+
1.0 "1.000000"
24+
0.1 "0.100000"
25+
1.1 "1.100000"
26+
1234.5678 "1234.567800"
27+
-1 "-1"
28+
-0.1 "-0.100000"
29+
-1.1 "-1.100000"
30+
-1234.5678 "-1234.567800"
31+
1e1 "10.000000"
32+
3/1 "3"))
33+
34+
(deftest test-vectors
35+
(assert-table [x y] (assert= (json/write-string x) y)
36+
[] "[]"
37+
[nil] "[null]"
38+
[1 2] "[1, 2]"
39+
[1 1.0 nil] "[1, 1.000000, null]"
40+
["foo" 42] "[\"foo\", 42]"))
41+
42+
(deftest test-seqs
43+
(assert-table [x y] (assert= (json/write-string x) y)
44+
(take 0 (range)) "[]"
45+
(take 1 (repeat nil)) "[null]"
46+
(map identity [1 2]) "[1, 2]"
47+
(reduce + [1 2 3]) "6"))
48+
49+
(deftest test-lists
50+
(assert-table [x y] (assert= (json/write-string x) y)
51+
'() "[]"
52+
'(nil) "[null]"
53+
'(1 2) "[1, 2]"
54+
'(1 1.0 nil) "[1, 1.000000, null]"
55+
'("foo" 42) "[\"foo\", 42]"
56+
(list) "[]"
57+
(list nil) "[null]"
58+
(list 1 2) "[1, 2]"
59+
(list 1 1.0 nil) "[1, 1.000000, null]"
60+
(list "foo" 42) "[\"foo\", 42]"))
61+
62+
(deftest test-maps
63+
(assert-table [x y] (assert= (json/write-string x) y)
64+
{} "{}"
65+
{:foo 42} "{\"foo\": 42}"
66+
{"foo" 42} "{\"foo\": 42}"
67+
{"foo" 42, "bar" nil} "{\"foo\": 42, \"bar\": null}"))
68+
69+
(deftest test-round-trip
70+
(let [data {"foo" 1, "bar" [2 3]}] ; won't work with keywords because the parser doesn't keywordise them (yet)
71+
(assert= (-> data json/write-string json/read-string)
72+
data))
73+
74+
(let [string "{\"foo\": [1, 2, 3]}"]
75+
(assert= (-> string json/read-string json/write-string)
76+
string)))

0 commit comments

Comments
 (0)