Skip to content

Commit 097ff88

Browse files
cblpbergmark
authored andcommitted
Fix Natural parsing
1 parent b9da969 commit 097ff88

File tree

4 files changed

+31
-10
lines changed

4 files changed

+31
-10
lines changed

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Changes that affect users of aeson should be mentioned in `changelog.md`. It sho
88
* When it should be used
99
* What it supersedes
1010

11-
Add this entry under an `# Upcoming` header above existing releases.
11+
Add this entry under an `## Upcoming` header above existing releases.
1212

1313
The exact format of entries is not important as we'll go through everything before a release is made.
1414

Data/Aeson/Types/FromJSON.hs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ parseIntegralFromScientific :: forall a. Integral a => String -> Scientific -> P
188188
parseIntegralFromScientific expected s =
189189
case Scientific.floatingOrInteger s :: Either Double a of
190190
Right x -> pure x
191-
Left _ -> fail $ "Floating number specified for " ++ expected ++ ": " ++ show s
191+
Left _ -> fail $ "expected " ++ expected ++ ", encountered floating number " ++ show s
192192
{-# INLINE parseIntegralFromScientific #-}
193193

194194
parseIntegral :: Integral a => String -> Value -> Parser a
@@ -1273,16 +1273,20 @@ instance FromJSONKey Integer where
12731273
fromJSONKey = FromJSONKeyTextParser $ parseIntegralText "Integer"
12741274

12751275
instance FromJSON Natural where
1276-
parseJSON = withScientific "Natural" $ \s ->
1277-
if Scientific.coefficient s < 0
1278-
then fail $ "Expected a Natural number but got the negative number: " <> show s
1279-
else pure $ truncate s
1276+
parseJSON value = do
1277+
integer :: Integer <- parseIntegral "Natural" value
1278+
if integer < 0 then
1279+
fail $ "expected Natural, encountered negative number " <> show integer
1280+
else
1281+
pure $ fromIntegral integer
12801282

12811283
instance FromJSONKey Natural where
1282-
fromJSONKey = FromJSONKeyTextParser $ \t -> parseScientificText t >>= \s ->
1283-
if Scientific.coefficient s < 0
1284-
then fail $ "Expected a Natural number but got the negative number: " <> show s
1285-
else pure $ truncate s
1284+
fromJSONKey = FromJSONKeyTextParser $ \text -> do
1285+
integer :: Integer <- parseIntegralText "Natural" text
1286+
if integer < 0 then
1287+
fail $ "expected Natural, encountered negative number " <> show integer
1288+
else
1289+
pure $ fromIntegral integer
12861290

12871291
instance FromJSON Int8 where
12881292
parseJSON = parseBoundedIntegral "Int8"

changelog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ For the latest version of this document, please see [https://github.com/bos/aeso
33
## Upcoming
44

55
* Add `FromJSON` and `ToJSON` instances for `DiffTime`, thanks to Víctor López Juan
6+
* Fix handling of fractions when parsing Natural.
7+
Change text in error messages for Integral types to make them follow the common pattern.
8+
PVP level is "Non-breaking change".
69

710
## 1.2.1.0
811

tests/ErrorMessages.hs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import Prelude.Compat
1212
import Data.Aeson (FromJSON(..), eitherDecode)
1313
import Data.Proxy (Proxy(..))
1414
import Instances ()
15+
import Numeric.Natural (Natural)
1516
import Test.Framework (Test)
1617
import Test.Framework.Providers.HUnit (testCase)
1718
import Test.HUnit (Assertion, assertFailure, assertEqual)
@@ -22,6 +23,8 @@ tests :: [Test]
2223
tests =
2324
[
2425
testCase "Int" int
26+
, testCase "Integer" integer
27+
, testCase "Natural" natural
2528
, testCase "String" string
2629
, testCase "HashMap" hashMap
2730
]
@@ -34,6 +37,17 @@ int = do
3437
t "{}" $ expected "Int" "Object"
3538
t "null" $ expected "Int" "Null"
3639

40+
integer :: Assertion
41+
integer = do
42+
let t = test (Proxy :: Proxy Integer)
43+
t "44.44" $ expected "Integer" "floating number 44.44"
44+
45+
natural :: Assertion
46+
natural = do
47+
let t = test (Proxy :: Proxy Natural)
48+
t "44.44" $ expected "Natural" "floating number 44.44"
49+
t "-50" $ expected "Natural" "negative number -50"
50+
3751
string :: Assertion
3852
string = do
3953
let t = test (Proxy :: Proxy String)

0 commit comments

Comments
 (0)