mirror of
https://github.com/rowtype-yoga/purescript-yoga-json.git
synced 2024-12-01 20:03:15 +03:00
Add support for bigint (#5)
* Add support for bigint Add multiple deserialisation options * Add npm install
This commit is contained in:
parent
353f5aa5aa
commit
0c1654c631
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -31,7 +31,7 @@ jobs:
|
||||
path: |
|
||||
.spago
|
||||
output
|
||||
|
||||
- run: npm install
|
||||
- run: spago build
|
||||
|
||||
- run: spago -x test.dhall test
|
||||
|
27
package-lock.json
generated
Normal file
27
package-lock.json
generated
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "purescript-yoga-json",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"big-integer": "^1.6.51"
|
||||
}
|
||||
},
|
||||
"node_modules/big-integer": {
|
||||
"version": "1.6.51",
|
||||
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz",
|
||||
"integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==",
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"big-integer": {
|
||||
"version": "1.6.51",
|
||||
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz",
|
||||
"integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg=="
|
||||
}
|
||||
}
|
||||
}
|
6
package.json
Normal file
6
package.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"big-integer": "^1.6.51"
|
||||
},
|
||||
"type": "module"
|
||||
}
|
@ -4,6 +4,8 @@
|
||||
, dependencies =
|
||||
[ "arrays"
|
||||
, "bifunctors"
|
||||
, "bigints"
|
||||
, "console"
|
||||
, "control"
|
||||
, "effect"
|
||||
, "either"
|
||||
|
@ -1,5 +1,18 @@
|
||||
export const _parseJSON = JSON.parse;
|
||||
function reviver(key, value) {
|
||||
if (key === 'big') {
|
||||
return BigInt(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
export const _parseJSON = (payload) => JSON.parse(payload, reviver);
|
||||
|
||||
export const _undefined = undefined;
|
||||
|
||||
export const _unsafeStringify = JSON.stringify;
|
||||
function replacer(key, value) {
|
||||
if (key === 'big') {
|
||||
return value.toString();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
export const _unsafeStringify = (data) => JSON.stringify(data, replacer);
|
||||
|
@ -39,11 +39,13 @@ import Control.Monad.Except (ExceptT(..), except, runExcept, throwError, withExc
|
||||
import Data.Array as Array
|
||||
import Data.Array.NonEmpty (NonEmptyArray, fromArray, toArray)
|
||||
import Data.Bifunctor (lmap)
|
||||
import Data.BigInt (BigInt)
|
||||
import Data.BigInt as BigInt
|
||||
import Data.Either (Either, hush, note)
|
||||
import Data.FoldableWithIndex (foldrWithIndex)
|
||||
import Data.Identity (Identity(..))
|
||||
import Data.Int as Int
|
||||
import Data.List.NonEmpty (singleton)
|
||||
import Data.List.NonEmpty (NonEmptyList, singleton)
|
||||
import Data.Map (Map)
|
||||
import Data.Map as Map
|
||||
import Data.Maybe (Maybe(..), fromMaybe, fromMaybe', maybe)
|
||||
@ -57,7 +59,7 @@ import Data.Variant (Variant, inj, on)
|
||||
import Effect.Exception (message, try)
|
||||
import Effect.Uncurried as EU
|
||||
import Effect.Unsafe (unsafePerformEffect)
|
||||
import Foreign (F, Foreign, ForeignError(..), MultipleErrors, fail, isNull, isUndefined, readArray, readBoolean, readChar, readInt, readNull, readNumber, readString, tagOf, unsafeFromForeign, unsafeToForeign)
|
||||
import Foreign (F, Foreign, ForeignError(..), MultipleErrors, fail, isNull, isUndefined, readArray, readBoolean, readChar, readInt, readNull, readNumber, readString, tagOf, unsafeFromForeign, unsafeReadTagged, unsafeToForeign)
|
||||
import Foreign.Index (readProp)
|
||||
import Foreign.Object (Object)
|
||||
import Foreign.Object as Object
|
||||
@ -177,6 +179,24 @@ instance ReadForeign Number where
|
||||
instance ReadForeign Int where
|
||||
readImpl = readInt
|
||||
|
||||
-- | Attempt to coerce a foreign value to a `BigInt`.
|
||||
readBigInt ∷
|
||||
∀ m. Monad m ⇒ Foreign → ExceptT (NonEmptyList ForeignError) m BigInt
|
||||
readBigInt = unsafeReadTagged "BigInt"
|
||||
|
||||
instance ReadForeign BigInt where
|
||||
readImpl fValue = tryInt fValue <|> readBigInt fValue <|> tryString fValue
|
||||
where
|
||||
tryInt f = readInt f <#> BigInt.fromInt
|
||||
tryString f = do
|
||||
bi ← readString f
|
||||
BigInt.fromString bi
|
||||
# note
|
||||
( singleton $ ForeignError $ "String " <> bi <>
|
||||
" could not be converted to BigInt"
|
||||
)
|
||||
# except
|
||||
|
||||
instance ReadForeign String where
|
||||
readImpl = readString
|
||||
|
||||
@ -351,6 +371,9 @@ instance WriteForeign Char where
|
||||
instance WriteForeign Number where
|
||||
writeImpl = unsafeToForeign
|
||||
|
||||
instance WriteForeign BigInt where
|
||||
writeImpl = unsafeToForeign
|
||||
|
||||
instance WriteForeign Boolean where
|
||||
writeImpl = unsafeToForeign
|
||||
|
||||
@ -484,4 +507,4 @@ instance (Newtype nt key, ReadForeign (Map key value)) => ReadForeign (Map nt va
|
||||
|
||||
unsafeStringToInt :: String → Int
|
||||
unsafeStringToInt = Int.fromString >>>
|
||||
(fromMaybe' \_ -> unsafeCrashWith "impossible")
|
||||
(fromMaybe' \_ -> unsafeCrashWith "impossible")
|
||||
|
@ -3,6 +3,7 @@ module Test.BasicsSpec where
|
||||
import Prelude
|
||||
|
||||
import Data.Array.NonEmpty as NEA
|
||||
import Data.BigInt (BigInt)
|
||||
import Data.Either (Either(..))
|
||||
import Data.Foldable (traverse_)
|
||||
import Data.List as List
|
||||
@ -51,7 +52,26 @@ spec = describe "En- and decoding" $ do
|
||||
$ roundtrips (Map.fromFoldable [(Stringy "A" /\ "B"),(Stringy "C" /\ "D")])
|
||||
it "roundtrips Map with Int newtype keys"
|
||||
$ roundtrips (Map.fromFoldable [(Inty 4 /\ "B"),(Inty 8 /\ "D")])
|
||||
it "roundtrips BigInt" do
|
||||
let
|
||||
inputStr = """{ "number":1, "big": 18014398509481982, "smallBig": 10 }"""
|
||||
expected = """{"smallBig":"10","number":1,"big":"18014398509481982"}"""
|
||||
parsed ∷ _ ({ number ∷ Int, big ∷ BigInt, smallBig ∷ BigInt })
|
||||
parsed = readJSON inputStr
|
||||
stringified = parsed <#> writeJSON
|
||||
stringified `shouldEqual` (Right expected)
|
||||
-- [TODO] Comment in as soon as bug in big-integers is fixed
|
||||
-- it "roundtrips BigInt (2)" do
|
||||
-- let
|
||||
-- smallBig = BigInt.fromInt 10
|
||||
-- big = unsafePartial $ fromJust $ BigInt.fromString "18014398509481982"
|
||||
|
||||
-- expected = { big, smallBig }
|
||||
-- json = spy "json" $ writeJSON expected
|
||||
|
||||
-- parsed ∷ _ ({ big ∷ BigInt, smallBig ∷ BigInt })
|
||||
-- parsed = readJSON json
|
||||
-- (spy "parsed" parsed) `shouldEqual` (Right expected)
|
||||
describe "works on record types" do
|
||||
it "roundtrips" do
|
||||
roundtrips { a: 12, b: "54" }
|
||||
@ -111,4 +131,4 @@ derive newtype instance Show Inty
|
||||
derive newtype instance Eq Inty
|
||||
derive newtype instance Ord Inty
|
||||
derive newtype instance WriteForeign Inty
|
||||
derive newtype instance ReadForeign Inty
|
||||
derive newtype instance ReadForeign Inty
|
||||
|
Loading…
Reference in New Issue
Block a user