packages feed

JSONb-1.0.0: examples/JSONSchema.hs

#!/usr/bin/env runhaskell


{-# LANGUAGE NoMonomorphismRestriction
  #-}


import Prelude hiding
  ( interact
  , lines
  , unlines
  , tail
  , null
  , unwords
  , length
  , repeat
  , elem
  , take
  , concat
  )
import System.Exit
import System.IO (stderr, stdout)
import System.Environment
import Data.ByteString (hPutStr)
import Data.ByteString.Char8 hiding (any, reverse, foldr)
import Data.ByteString.Lazy.Char8 (toChunks)
import Data.Word
import qualified Data.Set as Set

import qualified Data.Trie as Trie

import qualified Text.JSONb as JSONb




help                         =  (unlines . fmap pack)
  [ "USAGE: json-schema (--any|--count|--one-many)? < json_file.json"
  , ""
  , "Derives a schema for JSON input, counting according to the option"
  , "spec or using one-many counting by default. An example is probably best."
  , "JSON that looks this:"
  , ""
  , "  { id: 0, name: \"molly\", windage: 1.2 }"
  , "  { id: 0, name: \"edmund\", windage: null }"
  , ""
  , "is assigned this schema under one-many counting:"
  , ""
  , "  { id      : num"
  , "    name    : str"
  , "    windage : num | null"
  , "  }+"
  , ""
  , "but is assigned this schema under plain old integral counting:"
  , ""
  , "  { id      : num"
  , "    name    : str"
  , "    windage : num | null"
  , "  } 2"
  , ""
  , "and is assigned this schema under any counting:"
  , ""
  , "  { id      : num"
  , "    name    : str"
  , "    windage : num | null"
  , "  }"
  , ""
  , "Notice that properties sum types; the schema inferencer assumes JSON"
  , "objects with like property names are the same object type."
  , ""
  ]


main                         =  do
  args                      <-  getArgs
  case args of
    []                      ->  op (JSONb.schemas :: Counting JSONb.OneMany)
    ["--any"]               ->  op (JSONb.schemas :: Counting ())
    ["--one-many"]          ->  op (JSONb.schemas :: Counting JSONb.OneMany)
    ["--count"]             ->  op (JSONb.schemas :: Counting Word)
    ["-h"]                  ->  hPutStr stdout help
    ["-?"]                  ->  hPutStr stdout help
    ["--help"]              ->  hPutStr stdout help
    _                       ->  do
      hPutStr stderr $ pack "!!  Invalid option or options.\n"
      hPutStr stderr help
      exitFailure
 where
  op schemas                 =  interact (display . schemas . progressive)


display                      =  unlines . fmap (strictify . JSONb.bytes)
 where
  strictify                  =  concat . toChunks


progressive                  =  progressive_parse' []
 where
  progressive_parse' acc bytes
    | null bytes             =  reverse acc
    | otherwise              =  case JSONb.break bytes of
      (Left _, _)           ->  progressive_parse' acc (tail bytes)
      (Right piece, rem)    ->  progressive_parse' (piece:acc) rem


type Counting c              =  [JSONb.JSON] -> [(c, JSONb.Schema c)]