8 | module JSON.Simple.FromJSON
10 | import Data.List.Quantifiers as LQ
11 | import Data.Vect.Quantifiers as VQ
12 | import Data.SortedMap
13 | import Data.Singleton
14 | import Derive.Prelude
16 | import JSON.Simple.Option
17 | import JSON.Simple.ToJSON
19 | import Text.ILex.State.Regular
21 | %language ElabReflection
30 | data JSONPathElement = Key String | Index Bits32
32 | %runElab derive "JSONPathElement" [Show,Eq]
36 | JSONPath = List JSONPathElement
40 | JSONErr = (JSONPath,String)
43 | Result : Type -> Type
44 | Result = Either JSONErr
47 | Parser : Type -> Type -> Type
48 | Parser v a = v -> Either JSONErr a
51 | orElse : Either a b -> Lazy (Either a b) -> Either a b
52 | orElse r@(Right _) _ = r
56 | (<|>) : Parser v a -> Parser v a -> Parser v a
57 | f <|> g = \vv => f vv `orElse` g vv
60 | data DecodingErr : Type where
61 | JErr : JSONErr -> DecodingErr
62 | JParseErr : ParseError Void -> DecodingErr
64 | %runElab derive "DecodingErr" [Show,Eq]
67 | DecodingResult : Type -> Type
68 | DecodingResult = Either DecodingErr
77 | formatRelativePath : JSONPath -> String
78 | formatRelativePath path = format "" path
80 | isIdentifierKey : List Char -> Bool
81 | isIdentifierKey [] = False
82 | isIdentifierKey (x::xs) = isAlpha x && all isAlphaNum xs
84 | escapeChar : Char -> String
85 | escapeChar '\'' = "\\'"
86 | escapeChar '\\' = "\\\\"
87 | escapeChar c = singleton c
89 | escapeKey : List Char -> String
90 | escapeKey = fastConcat . map escapeChar
92 | formatKey : String -> String
94 | let chars = fastUnpack key
95 | in if isIdentifierKey chars then fastPack $
'.' :: chars
96 | else "['" ++ escapeKey chars ++ "']"
98 | format : String -> JSONPath -> String
100 | format pfx (Index idx :: parts) = format (pfx ++ "[" ++ show idx ++ "]") parts
101 | format pfx (Key key :: parts) = format (pfx ++ formatKey key) parts
106 | formatPath : JSONPath -> String
107 | formatPath path = "$" ++ formatRelativePath path
112 | formatError : JSONPath -> String -> String
113 | formatError path msg = "Error in " ++ formatPath path ++ ": " ++ msg
116 | Interpolation DecodingErr where
117 | interpolate (JErr (p,s)) = formatError p s
118 | interpolate (JParseErr x) = interpolate x
125 | prettyErr : (input : String) -> DecodingErr -> String
126 | prettyErr _ = interpolate
133 | interface FromJSON a where
134 | constructor MkFromJSON
135 | fromJSON : Parser JSON a
138 | interface FromJSONKey a where
139 | constructor MkFromJSONKey
140 | fromKey : Parser String a
143 | decode : FromJSON a => String -> DecodingResult a
145 | let Right json := parseJSON Virtual s | Left err => Left (JParseErr err)
146 | Right res := fromJSON json | Left p => Left (JErr p)
150 | decodeEither : FromJSON a => String -> Either String a
151 | decodeEither s = mapFst interpolate $
decode s
154 | decodeMaybe : FromJSON a => String -> Maybe a
155 | decodeMaybe = either (const Nothing) Just . decode
162 | typeOf : JSON -> String
163 | typeOf JNull = "Null"
164 | typeOf (JBool _) = "Boolean"
165 | typeOf (JDouble _) = "Double"
166 | typeOf (JInteger _) = "Integer"
167 | typeOf (JString _) = "String"
168 | typeOf (JArray _) = "Array"
169 | typeOf (JObject _) = "Object"
172 | fail : String -> Result a
173 | fail s = Left (Nil,s)
175 | typeMismatch : String -> Parser JSON a
176 | typeMismatch expected actual =
177 | fail $
"expected \{expected}, but encountered \{typeOf actual}"
179 | unexpected : Parser JSON a
180 | unexpected actual = fail $
"unexpected \{typeOf actual}"
183 | modifyFailure : (String -> String) -> Result a -> Result a
184 | modifyFailure f = mapFst (map f)
189 | prependFailure : String -> Result a -> Result a
190 | prependFailure = modifyFailure . (++)
193 | prependContext : String -> Result a -> Result a
194 | prependContext name = prependFailure "parsing \{name} failed, "
197 | prependPath : Result a -> JSONPathElement -> Result a
198 | prependPath r elem = mapFst (\(path,s) => (elem :: path,s)) r
202 | -> (JSON -> Maybe t)
203 | -> (name : Lazy String)
206 | withValue s get n f val =
209 | Nothing => prependContext n $
typeMismatch s val
212 | withKey : Parser String a -> Parser String a
213 | withKey f = prependFailure "parsing key failed, " . f
216 | withObject : Lazy String -> Parser (List (String,JSON)) a -> Parser JSON a
217 | withObject = withValue "Object" $
\case JObject ps => Just ps;
_ => Nothing
220 | withBoolean : Lazy String -> Parser Bool a -> Parser JSON a
221 | withBoolean = withValue "Boolean" $
\case JBool b => Just b;
_ => Nothing
224 | withString : Lazy String -> Parser String a -> Parser JSON a
225 | withString = withValue "String" $
\case JString s => Just s;
_ => Nothing
228 | withNull : String -> t -> Parser JSON t
229 | withNull s x JNull = Right x
231 | prependContext s $
fail "expexted Null but encountered \{typeOf v}"
234 | eqString : Lazy String -> String -> Parser JSON ()
235 | eqString n s = withString n $
\s' =>
236 | if s == s' then Right () else fail "expected '\{s}' but got '\{s'}'"
239 | withDouble : Lazy String -> Parser Double a -> Parser JSON a
241 | withValue "Double" $
\case
242 | JDouble d => Just d
243 | JInteger n => Just (cast n)
247 | withInteger : Lazy String -> Parser Integer a -> Parser JSON a
248 | withInteger = withValue "Integer" $
\case JInteger d => Just d;
_ => Nothing
251 | pint1 : PVal1 q Void Integer
252 | pint1 = value Nothing [(decimal, bytes decimal)]
255 | withIntegerKey : Parser Integer a -> Parser String a
258 | case parseString pint1 Virtual s of
260 | Left _ => fail "not an integer: \{s}"
266 | -> (lower : Integer)
267 | -> (upper : Integer)
269 | boundedIntegral s lo up =
270 | withInteger s $
\n =>
271 | if n >= lo && n <= up
272 | then Right $
fromInteger n
273 | else fail "integer out of bounds: \{show n}"
276 | boundedIntegralKey :
278 | -> (lower : Integer)
279 | -> (upper : Integer)
281 | boundedIntegralKey lo up =
282 | withIntegerKey $
\n =>
283 | if n >= lo && n <= up
284 | then Right $
fromInteger n
285 | else fail "integer out of bounds: \{show n}"
288 | withArray : Lazy String -> Parser (List JSON) a -> Parser JSON a
289 | withArray = withValue "Array" $
\case JArray v => Just v;
_ => Nothing
295 | -> Parser (Vect n JSON) a
297 | withArrayN n = withValue "Array of length \{show n}" $
298 | \case JArray v => toVect n v;
_ => Nothing
302 | explicitParseField : Parser JSON a -> List (String,JSON) -> Parser String a
303 | explicitParseField p o key =
304 | case lookup key o of
305 | Nothing => fail "key \{show key} not found"
306 | Just v => p v `prependPath` Key key
310 | explicitParseFieldMaybe :
312 | -> List (String,JSON)
313 | -> Parser String (Maybe a)
314 | explicitParseFieldMaybe p o key =
315 | case lookup key o of
316 | Nothing => Right Nothing
317 | Just JNull => Right Nothing
318 | Just v => map Just $
p v `prependPath` Key key
322 | explicitParseFieldMaybe' :
324 | -> List (String,JSON)
326 | explicitParseFieldMaybe' p o key =
327 | case lookup key o of
328 | Nothing => p JNull `prependPath` Key key
329 | Just v => p v `prependPath` Key key
339 | field : FromJSON a => List (String,JSON) -> Parser String a
340 | field = explicitParseField fromJSON
350 | fieldMaybe : FromJSON a => List (String,JSON) -> Parser String (Maybe a)
351 | fieldMaybe = explicitParseFieldMaybe fromJSON
359 | optField : FromJSON a => List (String,JSON) -> Parser String a
360 | optField = explicitParseFieldMaybe' fromJSON
365 | fieldWithDeflt : FromJSON a => List (String,JSON) -> Lazy a -> Parser String a
366 | fieldWithDeflt ps v s = fromMaybe v <$> fieldMaybe ps s
373 | FromJSON JSON where fromJSON = Right
376 | FromJSON Void where
377 | fromJSON v = fail "Cannot parse Void"
381 | fromJSON = withArray "()" $
382 | \case Nil => Right ()
383 | _ :: _ => fail "parsing () failed, expected empty list"
386 | FromJSON Bool where
387 | fromJSON = withBoolean "Bool" Right
390 | FromJSONKey Bool where
393 | \case "True" => Right True
394 | "False" => Right False
395 | s => fail "not a bool: \{s}"
398 | FromJSON Double where
399 | fromJSON = withDouble "Double" Right
402 | pdbl1 : PVal1 q Void Double
403 | pdbl1 = value Nothing [(jsonDouble, txt jdouble)]
406 | FromJSONKey Double where
409 | case parseString pdbl1 Virtual s of
411 | Left _ => fail "not a floating point number: \{s}"
414 | FromJSON Bits8 where
415 | fromJSON = boundedIntegral "Bits8" 0 0xff
418 | FromJSON Bits16 where
419 | fromJSON = boundedIntegral "Bits16" 0 0xffff
422 | FromJSON Bits32 where
423 | fromJSON = boundedIntegral "Bits32" 0 0xffffffff
426 | FromJSON Bits64 where
427 | fromJSON = boundedIntegral "Bits64" 0 0xffffffffffffffff
431 | fromJSON = boundedIntegral "Int" (-
0x8000000000000000) 0x7fffffffffffffff
434 | FromJSON Int8 where
435 | fromJSON = boundedIntegral "Int8" (-
0x80) 0x7f
438 | FromJSON Int16 where
439 | fromJSON = boundedIntegral "Int16" (-
0x8000) 0x7fff
442 | FromJSON Int32 where
443 | fromJSON = boundedIntegral "Int32" (-
0x80000000) 0x7fffffff
446 | FromJSON Int64 where
447 | fromJSON = boundedIntegral "Int64" (-
0x8000000000000000) 0x7fffffffffffffff
450 | FromJSONKey Bits8 where
451 | fromKey = boundedIntegralKey 0 0xff
454 | FromJSONKey Bits16 where
455 | fromKey = boundedIntegralKey 0 0xffff
458 | FromJSONKey Bits32 where
459 | fromKey = boundedIntegralKey 0 0xffffffff
462 | FromJSONKey Bits64 where
463 | fromKey = boundedIntegralKey 0 0xffffffffffffffff
466 | FromJSONKey Int where
467 | fromKey = boundedIntegralKey (-
0x8000000000000000) 0x7fffffffffffffff
470 | FromJSONKey Int8 where
471 | fromKey = boundedIntegralKey (-
0x80) 0x7f
474 | FromJSONKey Int16 where
475 | fromKey = boundedIntegralKey (-
0x8000) 0x7fff
478 | FromJSONKey Int32 where
479 | fromKey = boundedIntegralKey (-
0x80000000) 0x7fffffff
482 | FromJSONKey Int64 where
483 | fromKey = boundedIntegralKey (-
0x8000000000000000) 0x7fffffffffffffff
487 | fromJSON = withInteger "Nat" $
\n =>
488 | if n >= 0 then Right $
fromInteger n
489 | else fail "not a natural number: \{show n}"
492 | FromJSONKey Nat where
493 | fromKey = withIntegerKey $
\n =>
494 | if n >= 0 then Right $
fromInteger n
495 | else fail "not a natural number: \{show n}"
498 | FromJSON Integer where
499 | fromJSON = withInteger "Integer" Right
502 | FromJSONKey Integer where
503 | fromKey = withIntegerKey Right
506 | FromJSON String where
507 | fromJSON = withString "String" Right
510 | FromJSONKey String where
511 | fromKey = withKey Right
514 | FromJSON Char where
515 | fromJSON = withString "Char" $
\str =>
517 | StrCons c "" => Right c
518 | _ => fail "expected a string of length 1"
521 | FromJSONKey Char where
522 | fromKey = withKey $
\str =>
524 | StrCons c "" => Right c
525 | _ => fail "expected a string of length 1"
528 | FromJSON a => FromJSON (Maybe a) where
529 | fromJSON JNull = Right Nothing
530 | fromJSON v = Just <$> fromJSON v
533 | FromJSON a => FromJSON (List a) where
534 | fromJSON = withArray "List" $
traverse fromJSON
537 | FromJSON a => FromJSON (SnocList a) where
538 | fromJSON = map ([<] <><) . fromJSON
541 | FromJSON a => FromJSON (List1 a) where
542 | fromJSON = withArray "List1" $
\case
543 | Nil => fail "expected non-empty list"
544 | h :: t => traverse fromJSON (h ::: t)
547 | {v : a} -> FromJSON a => ToJSON a => Eq a => FromJSON (Singleton v) where
549 | fromJSON x >>= \val => case v == val of
550 | True => Right (Val v)
551 | False => fail "Invalid value. Expected \{encode v}"
555 | -> {auto jk : FromJSONKey k}
556 | -> {auto jv : FromJSON v}
558 | -> Parser (List (String,JSON)) (SortedMap k v)
559 | sortedMap m [] = Right m
560 | sortedMap m ((x,y) :: ps) =
561 | let Right k' := fromKey x | Left err => Left err
562 | Right v' := fromJSON y | Left err => Left err
563 | in sortedMap (insert k' v' m) ps
566 | Ord k => FromJSONKey k => FromJSON v => FromJSON (SortedMap k v) where
567 | fromJSON = withObject "SortedMap" (sortedMap empty)
570 | {n : Nat} -> FromJSON a => FromJSON (Vect n a) where
571 | fromJSON = withArray "Vect \{show n}" $
\vs => case toVect n vs of
572 | Just vect => traverse fromJSON vect
573 | Nothing => fail "expected list of length \{show n}"
576 | FromJSON a => FromJSON b => FromJSON (Either a b) where
577 | fromJSON = withObject "Either" $
\o =>
578 | map Left (field o "Left") `orElse`
579 | map Right (field o "Right")
582 | FromJSON a => FromJSON b => FromJSON (a, b) where
583 | fromJSON = withArray "Pair" $
584 | \case [x,y] => [| MkPair (fromJSON x) (fromJSON y) |]
585 | _ => fail "expected a pair of values"
587 | readLQ : (ps : LQ.All.All (FromJSON . f) ts) => Parser (List JSON) (All f ts)
588 | readLQ @{[]} [] = Right []
589 | readLQ @{_::_} (x :: xs) = [| fromJSON x :: readLQ xs |]
590 | readLQ @{_::_} [] = fail "list of values too short"
591 | readLQ @{[]} _ = fail "list of values too long"
593 | readVQ : (ps : VQ.All.All (FromJSON . f) ts) => Parser (List JSON) (All f ts)
594 | readVQ @{[]} [] = Right []
595 | readVQ @{_::_} (x :: xs) = [| fromJSON x :: readVQ xs |]
596 | readVQ @{_::_} [] = fail "list of values too short"
597 | readVQ @{[]} _ = fail "list of values too long"
600 | LQ.All.All (FromJSON . f) ts => FromJSON (All f ts) where
601 | fromJSON = withArray "HList" $
readLQ
604 | VQ.All.All (FromJSON . f) ts => FromJSON (VQ.All.All f ts) where
605 | fromJSON = withArray "HVect" $
readVQ
613 | (tpe : Lazy String)
614 | -> Parser (String,JSON) a
616 | fromSingleField n f = withObject n $
618 | _ => fail "expected single field object"
627 | (tpe : Lazy String)
628 | -> Parser (String,JSON) a
630 | fromTwoElemArray n f =
631 | withArrayN 2 n $
\[x,y] => withString n (\s => f (s,y)) x
640 | (tpe : Lazy String)
641 | -> (tagField, contentField : String)
642 | -> Parser (String,JSON) a
644 | fromTaggedObject n tf cf f = withObject n $
\o => do
646 | v <- explicitParseField Right o cf