1
1
# JSON schema to Elm
2
2
3
- Generates Elm types, JSON decoders and JSON encoders from JSON schema
4
- specifications.
3
+ Generates Elm types, JSON decoders, JSON encoders, and Fuzz tests from JSON
4
+ schema specifications.
5
5
6
6
## Installation
7
7
@@ -26,14 +26,14 @@ Run `./js2e` for usage instructions.
26
26
> have to pass it the enclosing directory of the relevant JSON schema files,
27
27
> in order for it to be able to resolve the references correctly.
28
28
29
- A proper description of which properties are mandatory are how the generator
29
+ A proper description of which properties are mandatory and how the generator
30
30
works is still in progress, but feel free to take a look at the ` examples `
31
31
folder which contains an example of a pair of JSON schemas and their
32
32
corresponding Elm output. Likewise, representations of each of the different
33
33
JSON schema types are described in the ` lib/types ` folder.
34
34
35
- The tool aims to produce ` elm-make ` -like errors if something is missing,
36
- mispelled or cannot be resolved in the supplied JSON schema file(s), e.g.
35
+ The tool aims to produce ` elm-make ` -like errors in case something is missing,
36
+ misspelled or cannot be resolved in the supplied JSON schema file(s), e.g.
37
37
38
38
```
39
39
--- UNKNOWN NODE TYPE -------------------------------------- all_of_example.json
@@ -137,21 +137,25 @@ type alias Point =
137
137
138
138
colorDecoder : String -> Decoder Color
139
139
colorDecoder color =
140
- case color of
141
- " red" ->
142
- succeed Red
140
+ Decode . string
141
+ |> andThen
142
+ ( \ color ->
143
+ case color of
144
+ " red" ->
145
+ succeed Red
143
146
144
- " yellow" ->
145
- succeed Yellow
147
+ " yellow" ->
148
+ succeed Yellow
146
149
147
- " green" ->
148
- succeed Green
150
+ " green" ->
151
+ succeed Green
149
152
150
- " blue" ->
151
- succeed Blue
153
+ " blue" ->
154
+ succeed Blue
152
155
153
- _ ->
154
- fail <| " Unknown color type: " ++ color
156
+ _ ->
157
+ fail <| " Unknown color type: " ++ color
158
+ )
155
159
156
160
157
161
pointDecoder : Decoder Point
@@ -253,34 +257,34 @@ import Json.Encode as Encode
253
257
, object
254
258
, list
255
259
)
256
- import Data.Definitions
260
+ import Data.Definitions as Definitions
257
261
258
262
259
263
type alias Circle =
260
- { center : Data . Definitions . Point
261
- , color : Maybe Data . Definitions . Color
264
+ { center : Definitions . Point
265
+ , color : Maybe Definitions . Color
262
266
, radius : Float
263
267
}
264
268
265
269
266
270
circleDecoder : Decoder Circle
267
271
circleDecoder =
268
272
decode Circle
269
- |> required " center" Data . Definitions . pointDecoder
270
- |> optional " color" ( Decode . string |> andThen Data . Definitions . colorDecoder |> maybe ) Nothing
273
+ |> required " center" Definitions . pointDecoder
274
+ |> optional " color" ( nullable Definitions . colorDecoder) Nothing
271
275
|> required " radius" Decode . float
272
276
273
277
274
278
encodeCircle : Circle -> Value
275
279
encodeCircle circle =
276
280
let
277
281
center =
278
- [ ( " center" , Data . Definitions . encodePoint circle. center ) ]
282
+ [ ( " center" , Definitions . encodePoint circle. center ) ]
279
283
280
284
color =
281
285
case circle. color of
282
286
Just color ->
283
- [ ( " color" , Data . Definitions . encodeColor color ) ]
287
+ [ ( " color" , Definitions . encodeColor color ) ]
284
288
285
289
Nothing ->
286
290
[]
@@ -294,6 +298,170 @@ encodeCircle circle =
294
298
++ radius
295
299
```
296
300
301
+ Furthermore, ` js2e ` also generates test files for the generated decoders and
302
+ encoders, which fuzzes instances of a given Elm type and tests that encoding it
303
+ as JSON and decoding it back into Elm returns the original instance of that
304
+ generated Elm type. In the above case, the following test files,
305
+ ` tests/Data/CircleTests.elm ` and ` tests/Data/DefinitionsTests.elm ` , are
306
+ generated:
307
+
308
+ ``` elm
309
+ module Data.CircleTests exposing (..)
310
+
311
+ -- Tests: Schema for a circle shape
312
+
313
+ import Expect exposing (Expectation )
314
+ import Fuzz exposing (Fuzzer )
315
+ import Test exposing (..)
316
+ import Json.Decode as Decode
317
+ import Data.Circle exposing (..)
318
+ import Data.DefinitionsTests as Definitions
319
+
320
+
321
+ circleFuzzer : Fuzzer Circle
322
+ circleFuzzer =
323
+ Fuzz . map3
324
+ Circle
325
+ Definitions . pointFuzzer
326
+ ( Fuzz . maybe Definitions . colorFuzzer)
327
+ Fuzz . float
328
+
329
+
330
+ encodeDecodeCircleTest : Test
331
+ encodeDecodeCircleTest =
332
+ fuzz circleFuzzer " can encode and decode Circle object" <|
333
+ \ circle ->
334
+ circle
335
+ |> encodeCircle
336
+ |> Decode . decodeValue circleDecoder
337
+ |> Expect . equal ( Ok circle)
338
+ ```
339
+ and
340
+
341
+ ``` elm
342
+ module Data.DefinitionsTests exposing (..)
343
+
344
+ -- Tests: Schema for common types
345
+
346
+ import Expect exposing (Expectation )
347
+ import Fuzz exposing (Fuzzer )
348
+ import Test exposing (..)
349
+ import Json.Decode as Decode
350
+ import Data.Definitions exposing (..)
351
+
352
+
353
+ colorFuzzer : Fuzzer Color
354
+ colorFuzzer =
355
+ Fuzz . oneOf
356
+ [ Fuzz . constant Red
357
+ , Fuzz . constant Yellow
358
+ , Fuzz . constant Green
359
+ , Fuzz . constant Blue
360
+ ]
361
+
362
+
363
+ encodeDecodeColorTest : Test
364
+ encodeDecodeColorTest =
365
+ fuzz colorFuzzer " can encode and decode Color object" <|
366
+ \ color ->
367
+ color
368
+ |> encodeColor
369
+ |> Decode . decodeValue colorDecoder
370
+ |> Expect . equal ( Ok color)
371
+
372
+
373
+ pointFuzzer : Fuzzer Point
374
+ pointFuzzer =
375
+ Fuzz . map2
376
+ Point
377
+ Fuzz . float
378
+ Fuzz . float
379
+
380
+
381
+ encodeDecodePointTest : Test
382
+ encodeDecodePointTest =
383
+ fuzz pointFuzzer " can encode and decode Point object" <|
384
+ \ point ->
385
+ point
386
+ |> encodePoint
387
+ |> Decode . decodeValue pointDecoder
388
+ |> Expect . equal ( Ok point)
389
+
390
+ ```
391
+
392
+ Finally, ` js2e ` also generates package config files, ` package.json ` and
393
+ ` elm-package.json ` making it easy to test that the generated Elm code is
394
+ behaving as expected. Thus, if we supply the following directory structure to
395
+ ` js2e ` in the above case:
396
+
397
+ ```
398
+ .
399
+ └── js2e_input/
400
+ ├── definitions.json
401
+ └── circle.json
402
+ ```
403
+
404
+ the following new directory structure is generated:
405
+
406
+ ```
407
+ .
408
+ └── js2e_output/
409
+ ├── package.json
410
+ ├── elm-package.json
411
+ ├── Data/
412
+ │ ├── Circle.elm
413
+ │ └── Definitions.elm
414
+ └── tests/
415
+ ├── elm-package.json
416
+ └── Data/
417
+ ├── CircleTests.elm
418
+ └── DefinitionsTests.elm
419
+ ```
420
+
421
+ containing the files described above along with the needed package config files
422
+ to compile and run the tests.
423
+
424
+ ## Error reporting
425
+
426
+ Any errors encountered by the ` js2e ` tool while parsing the JSON schema files or
427
+ printing the Elm code output, is reported in an Elm-like style, e.g.
428
+
429
+ ```
430
+ --- UNKNOWN NODE TYPE -------------------------------------- all_of_example.json
431
+
432
+ The value of "type" at '#/allOf/0/properties/description' did not match a known node type
433
+
434
+ "type": "strink"
435
+ ^^^^^^^^
436
+
437
+ Was expecting one of the following types
438
+
439
+ ["null", "boolean", "object", "array", "number", "integer", "string"]
440
+
441
+ Hint: See the specification section 6.25. "Validation keywords - type"
442
+ <http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.25>
443
+ ```
444
+
445
+ or
446
+
447
+ ```
448
+ --- UNRESOLVED REFERENCE ----------------------------------- all_of_example.json
449
+
450
+
451
+ The following reference at `#/allOf/0/color` could not be resolved
452
+
453
+ "$ref": #/definitions/kolor
454
+ ^^^^^^^^^^^^^^^^^^^
455
+
456
+
457
+ Hint: See the specification section 9. "Base URI and dereferencing"
458
+ <http://json-schema.org/latest/json-schema-core.html#rfc.section.9>
459
+ ```
460
+
461
+ If you encounter an error while using ` js2e ` that does not mimic the above
462
+ Elm-like style, but instead looks like an Elixir stacktrace, please report this
463
+ as a bug by opening an issue and includin a JSON schema example that recreates
464
+ the error.
297
465
298
466
## Contributing
299
467
0 commit comments