@@ -40,7 +40,6 @@ import Foreign.Object.ST as FOST
4040import Prim.Row as Row
4141import Record as Record
4242import Type.Proxy (Proxy (..))
43- import Unsafe.Coerce (unsafeCoerce )
4443
4544-- | A helper for defining JSON codecs for "enum" sum types, where every
4645-- | constructor is nullary, and the type will be encoded as a string.
@@ -109,6 +108,8 @@ data Encoding
109108 , omitEmptyArguments ∷ Boolean
110109 , unwrapSingleArguments ∷ Boolean
111110 }
111+ | EncodeUntagged
112+ { unwrapSingleArguments ∷ Boolean }
112113
113114defaultEncoding ∷ Encoding
114115defaultEncoding = EncodeTagValue
@@ -149,7 +150,7 @@ instance gCasesConstructorNoArgs ∷
149150 let
150151 name = reflectSymbol @name Proxy ∷ String
151152 in
152- encodeCase encoding name []
153+ encodeSumCase encoding name []
153154
154155 gCasesDecode ∷ Encoding → Record r → Json → Either JsonDecodeError (Constructor name NoArguments )
155156 gCasesDecode encoding _ json = do
@@ -169,7 +170,7 @@ else instance gCasesConstructorSingleArg ∷
169170 codec = Record .get (Proxy @name) r ∷ JsonCodec a
170171 name = reflectSymbol @name Proxy ∷ String
171172 in
172- encodeCase encoding name [ CA .encode codec x ]
173+ encodeSumCase encoding name [ CA .encode codec x ]
173174
174175 gCasesDecode ∷ Encoding → Record r → Json → Either JsonDecodeError (Constructor name (Argument a ))
175176 gCasesDecode encoding r json = do
@@ -193,7 +194,7 @@ else instance gCasesConstructorManyArgs ∷
193194 name = reflectSymbol @name Proxy ∷ String
194195 jsons = gFieldsEncode encoding codecs rep ∷ Array Json
195196 in
196- encodeCase encoding name jsons
197+ encodeSumCase encoding name jsons
197198
198199 gCasesDecode ∷ Encoding → Record r → Json → Either JsonDecodeError (Constructor name args )
199200 gCasesDecode encoding r json = do
@@ -292,9 +293,53 @@ checkTag tagKey obj expectedTag = do
292293 $ throwError
293294 $ TypeMismatch (" Expecting tag `" <> expectedTag <> " `, got `" <> tag <> " `" )
294295
296+ parseNoFields ∷ Encoding → Json → String → Either JsonDecodeError Unit
297+ parseNoFields encoding json expectedTag =
298+ case encoding of
299+ EncodeCtorAsTag {} → do
300+ obj ← CA .decode jobject json
301+ val ←
302+ ( Obj .lookup expectedTag obj # note (TypeMismatch (" Expecting a property `" <> expectedTag <> " `" ))
303+ ) ∷ _ Json
304+ fields ← CA .decode CA .jarray val ∷ _ (Array Json )
305+ when (fields /= [] )
306+ $ throwError
307+ $ TypeMismatch " Expecting an empty array"
308+
309+ EncodeTagValue { tagKey, valuesKey, omitEmptyArguments } → do
310+ obj ← CA .decode jobject json
311+ checkTag tagKey obj expectedTag
312+ when (not omitEmptyArguments) do
313+ val ←
314+ ( Obj .lookup valuesKey obj
315+ # note (TypeMismatch (" Expecting a value property `" <> valuesKey <> " `" ))
316+ ) ∷ _ Json
317+ fields ← CA .decode CA .jarray val ∷ _ (Array Json )
318+ when (fields /= [] )
319+ $ throwError
320+ $ TypeMismatch " Expecting an empty array"
321+
322+ EncodeUntagged {} → do
323+ fields ← CA .decode CA .jarray json ∷ _ (Array Json )
324+ when (fields /= [] )
325+ $ throwError
326+ $ TypeMismatch " Expecting an empty array"
327+
295328parseSingleField ∷ Encoding → Json → String → Either JsonDecodeError Json
296329parseSingleField encoding json expectedTag = case encoding of
297- EncodeCtorAsTag { unwrapSingleArguments } → unsafeCoerce " todo"
330+ EncodeCtorAsTag { unwrapSingleArguments } → do
331+ obj ← CA .decode jobject json
332+ val ←
333+ ( Obj .lookup expectedTag obj # note (TypeMismatch (" Expecting a property `" <> expectedTag <> " `" ))
334+ ) ∷ _ Json
335+ if unwrapSingleArguments then
336+ pure val
337+ else do
338+ fields ← CA .decode CA .jarray val
339+ case fields of
340+ [ head ] → pure head
341+ _ → throwError $ TypeMismatch " Expecting exactly one element"
342+
298343 EncodeTagValue { tagKey, valuesKey, unwrapSingleArguments } → do
299344 obj ← CA .decode jobject json
300345 checkTag tagKey obj expectedTag
@@ -310,28 +355,25 @@ parseSingleField encoding json expectedTag = case encoding of
310355 [ head ] → pure head
311356 _ → throwError $ TypeMismatch " Expecting exactly one element"
312357
313- parseNoFields ∷ Encoding → Json → String → Either JsonDecodeError Unit
314- parseNoFields encoding json expectedTag =
315- case encoding of
316- EncodeCtorAsTag { unwrapSingleArguments } → unsafeCoerce " todo"
317- EncodeTagValue { tagKey, valuesKey, omitEmptyArguments } →
318- do
319- obj ← CA .decode jobject json
320- checkTag tagKey obj expectedTag
321- when (not omitEmptyArguments) do
322- val ←
323- ( Obj .lookup valuesKey obj
324- # note (TypeMismatch (" Expecting a value property `" <> valuesKey <> " `" ))
325- ) ∷ _ Json
326- fields ← CA .decode CA .jarray val ∷ _ (Array Json )
327- when (fields /= [] )
328- $ throwError
329- $ TypeMismatch " Expecting an empty array"
358+ EncodeUntagged { unwrapSingleArguments } → do
359+ if unwrapSingleArguments then
360+ pure json
361+ else do
362+ fields ← CA .decode CA .jarray json
363+ case fields of
364+ [ head ] → pure head
365+ _ → throwError $ TypeMismatch " Expecting exactly one element"
330366
331367parseManyFields ∷ Encoding → Json → String → Either JsonDecodeError (Array Json )
332368parseManyFields encoding json expectedTag =
333369 case encoding of
334- EncodeCtorAsTag { unwrapSingleArguments } → unsafeCoerce " todo"
370+ EncodeCtorAsTag {} → do
371+ obj ← CA .decode jobject json
372+ val ←
373+ ( Obj .lookup expectedTag obj # note (TypeMismatch (" Expecting a property `" <> expectedTag <> " `" ))
374+ ) ∷ _ Json
375+ CA .decode CA .jarray val
376+
335377 EncodeTagValue { tagKey, valuesKey } → do
336378 obj ← CA .decode jobject json
337379 checkTag tagKey obj expectedTag
@@ -341,10 +383,23 @@ parseManyFields encoding json expectedTag =
341383 ) ∷ _ Json
342384 CA .decode CA .jarray val
343385
344- encodeCase ∷ Encoding → String → Array Json → Json
345- encodeCase encoding tag jsons =
386+ EncodeUntagged {} →
387+ CA .decode CA .jarray json
388+
389+ encodeSumCase ∷ Encoding → String → Array Json → Json
390+ encodeSumCase encoding tag jsons =
346391 case encoding of
347- EncodeCtorAsTag { unwrapSingleArguments } → unsafeCoerce " todo"
392+ EncodeCtorAsTag { unwrapSingleArguments } →
393+ let
394+ val = case jsons of
395+ [] → CA .encode CA .jarray []
396+ [ json ] | unwrapSingleArguments → json
397+ manyJsons → CA .encode CA .jarray manyJsons
398+ in
399+ encode jobject $ Obj .fromFoldable
400+ [ tag /\ val
401+ ]
402+
348403 EncodeTagValue { tagKey, valuesKey, unwrapSingleArguments, omitEmptyArguments } →
349404 let
350405 tagEntry =
@@ -356,4 +411,10 @@ encodeCase encoding tag jsons =
356411 manyJsons → Just (valuesKey /\ CA .encode CA .jarray manyJsons)
357412 in
358413 encode jobject $ Obj .fromFoldable $ catMaybes
359- [ tagEntry, valEntry ]
414+ [ tagEntry, valEntry ]
415+
416+ EncodeUntagged { unwrapSingleArguments } →
417+ case jsons of
418+ [] → CA .encode CA .jarray []
419+ [ json ] | unwrapSingleArguments → json
420+ manyJsons → CA .encode CA .jarray manyJsons
0 commit comments