Skip to content

Commit 7923df5

Browse files
committed
Better error checking, docs
Signed-off-by: Dan S. Camper <[email protected]>
1 parent 8fc2721 commit 7923df5

File tree

5 files changed

+129
-12
lines changed

5 files changed

+129
-12
lines changed

LICENSE.txt

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
Licensed under the Apache License, Version 2.0 (the "License");
2+
you may not use this file except in compliance with the License.
3+
You may obtain a copy of the License at
4+
5+
http://www.apache.org/licenses/LICENSE-2.0
6+
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.

README.md

+85-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,89 @@
1-
# json2ecl
2-
### _Dan S. Camper_
1+
## Description
32

4-
This is a project to do ... something.
3+
json2ecl examines JSON data and deduces the ECL RECORD definitions necessary to parse it.
4+
The resulting ECL definitions are returned via standard out, suitable for piping or copying
5+
and pasting into your favorite IDE.
56

6-
## License
7+
JSON data can be supplied as one or more files or via standard input.
8+
9+
Multiple files, if provided, are parsed as if they should have the same record structure.
10+
This is useful for cases where you suspect that not all JSON key/value objects are fully
11+
defined in one file, but other files may contain the missing data.
12+
13+
## Requirements
14+
15+
This project was written using SBCL and it has not been tested with other flavors
16+
of Lisp. There are very few dependencies, however, so it should work out of the box
17+
with all of the common Lisp distributions.
18+
19+
The following dependencies are required:
20+
21+
- ASDF (version 3.3.6 or later)
22+
- Quicklisp
23+
- Buildapp
24+
- Used to build the binary
25+
- [https://www.xach.com/lisp/buildapp/](https://www.xach.com/lisp/buildapp/)
26+
27+
## How to Build (for *nix-compatible systems)
28+
29+
1. Clone this repo: `git clone https://github.com/dancamper/json2ecl.git`
30+
1. Change directory: `cd json2ecl`
31+
1. Run build script: ./build_binary.sh
32+
1. Final binary is now bin/json2ecl. You can move or copy that binary to a location on your path.
33+
34+
## How to Use
35+
36+
Usage: `json2ecl [OPTIONS] [FILE...]`
37+
38+
json2ecl examines JSON data and deduces the ECL RECORD definitions necessary to
39+
parse it. The resulting ECL definitions are returned via standard out, suitable
40+
for piping or copying and pasting into your favorite IDE.
741

8-
MIT
42+
JSON data can be supplied as one or more files or via standard input.
43+
44+
Multiple files, if provided, are parsed as if they should have the same record
45+
structure. This is useful for cases where you suspect that not all JSON
46+
key/value objects are fully defined in one file, but other files may contain the
47+
missing data.
48+
49+
```
50+
Options:
51+
-v, --version Display version and exit.
52+
-h, --help Display help and exit.
53+
```
54+
55+
## Examples
56+
57+
Assuming file foo.json contains the following contents:
58+
59+
```json
60+
{
61+
"foo": "bar",
62+
"start": 12,
63+
"end": 98.76
64+
}
65+
```
66+
67+
Simple parsing of those contents:
68+
69+
````
70+
$ json2ecl foo.json
71+
FOO_001_LAYOUT := RECORD
72+
UTF8 foo {XPATH('foo')};
73+
INTEGER start {XPATH('start')};
74+
REAL f_end {XPATH('end')};
75+
END;
76+
````
77+
78+
````
79+
$ cat foo.json | json2ecl
80+
TOPLEVEL_231_001_LAYOUT := RECORD
81+
UTF8 foo {XPATH('foo')};
82+
INTEGER start {XPATH('start')};
83+
REAL f_end {XPATH('end')};
84+
END;
85+
````
86+
87+
## License
988

89+
Apache 2.0

json2ecl.asd

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
:description "Examines JSON data and deduces the ECL RECORD definitions necessary to parse it."
1111
:author "Dan S. Camper"
1212
:license "MIT"
13-
:version "0.0.4"
13+
:version "0.0.5"
1414
:serial t
1515
:depends-on (#:adopt #:com.inuoe.jzon #:with-user-abort)
1616
:components ((:file "package")

json2ecl.lisp

+4-2
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@
7676
(null "STRING")
7777
(string "STRING")
7878
(utf8 "UTF8")
79-
(number "INTEGER")))
79+
(number "INTEGER")
80+
(float "REAL")))
8081

8182
(defun dataset-datatype-name (name)
8283
(format nil "DATASET(~A)" (layout-name name)))
@@ -148,12 +149,13 @@
148149
((eql nil) 'boolean)
149150
((eql null) 'null)
150151
(integer 'number)
151-
(double-float 'number)
152+
(double-float 'float)
152153
(string 'utf8)))
153154

154155
(defun common-type (new-type old-type)
155156
(cond ((not old-type) new-type)
156157
((or (eql old-type 'utf8) (eql new-type 'utf8)) 'utf8)
158+
((or (eql old-type 'float) (eql new-type 'float)) 'float)
157159
((not (eql old-type new-type)) 'string)
158160
(t new-type)))
159161

userio.lisp

+28-4
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,37 @@
2020
:short #\h
2121
:reduce (constantly t)))
2222

23+
(adopt:define-string *help-text*
24+
"json2ecl examines JSON data and deduces the ECL RECORD definitions necessary to parse it. ~
25+
The resulting ECL definitions are returned via standard out, suitable for piping or copying ~
26+
and pasting into your favorite IDE.~@
27+
~@
28+
JSON data can be supplied as one or more files or via standard input.~@
29+
~@
30+
Multiple files, if provided, are parsed as if they should have the same record structure. ~
31+
This is useful for cases where you suspect that not all JSON key/value objects are fully ~
32+
defined in one file, but other files may contain the missing data.")
33+
2334
(defparameter *ui*
2435
(adopt:make-interface :name "json2ecl"
25-
:usage "[OPTIONS] FILE ..."
36+
:usage "[OPTIONS] [FILE...]"
2637
:summary (format nil "analyze JSON data and emit ECL record ~
2738
definitions that can parse that data")
28-
:help (format nil "json2ecl examines JSON data and deduces ~
29-
the ECL RECORD definitions necessary to parse it.")
39+
:help *help-text*
3040
:contents (list
3141
*option-version*
3242
*option-help*)))
3343

3444
;;;
3545

36-
(define-condition user-error (error) ())
46+
(define-condition user-error (error)
47+
())
48+
49+
(define-condition missing-file (user-error)
50+
((path :initarg :path))
51+
(:report
52+
(lambda (c s)
53+
(format s "missing file '~A'" (slot-value c 'path)))))
3754

3855
;;;
3956

@@ -44,13 +61,20 @@
4461
(defun run (args)
4562
(let* ((argc (length args))
4663
(args (if (plusp argc) args (list *standard-input*))))
64+
;; Verify that files exist
65+
(when (plusp argc)
66+
(loop for input in args
67+
do (unless (uiop:probe-file* input)
68+
(error 'missing-file :path input))))
4769
(let ((toplevel-name (if (= argc 1)
4870
(pathname-name (uiop:probe-file* (car args)))
4971
(format nil "~A" (gensym "toplevel_"))))
5072
(result-obj nil))
73+
;; Parse files or standard input
5174
(loop for input in args
5275
do (let ((one-item (or (uiop:probe-file* input) input)))
5376
(setf result-obj (process-file-or-stream one-item result-obj))))
77+
;; Emit ECL record definitions
5478
(setf *layout-names* nil)
5579
(format t "~A" (as-ecl-recdef result-obj toplevel-name)))))
5680

0 commit comments

Comments
 (0)