on master help sign in
Fix Natural parsing
097ff88Yuriy Syrovetskiy
CONTRIBUTING.md+1−1
@@ -8,7 +8,7 @@ Changes that affect users of aeson should be mentioned in `changelog.md`. It sho
8 * When it should be used
8 * When it should be used
9 * What it supersedes
9 * What it supersedes
10
10
11−Add this entry under an `# Upcoming` header above existing releases.
11+Add this entry under an `## Upcoming` header above existing releases.
12
12
13The exact format of entries is not important as we'll go through everything before a release is made.
13The exact format of entries is not important as we'll go through everything before a release is made.
14
14
Data/Aeson/Types/FromJSON.hs+13−9
@@ -188,7 +188,7 @@ parseIntegralFromScientific :: forall a. Integral a => String -> Scientific -> P
188parseIntegralFromScientific expected s =
188parseIntegralFromScientific expected s =
189 case Scientific.floatingOrInteger s :: Either Double a of
189 case Scientific.floatingOrInteger s :: Either Double a of
190 Right x -> pure x
190 Right x -> pure x
191− Left _ -> fail $ "Floating number specified for " ++ expected ++ ": " ++ show s
191+ Left _ -> fail $ "expected " ++ expected ++ ", encountered floating number " ++ show s
192{-# INLINE parseIntegralFromScientific #-}
192{-# INLINE parseIntegralFromScientific #-}
193
193
194parseIntegral :: Integral a => String -> Value -> Parser a
194parseIntegral :: Integral a => String -> Value -> Parser a
@@ -1273,16 +1273,20 @@ instance FromJSONKey Integer where
1273 fromJSONKey = FromJSONKeyTextParser $ parseIntegralText "Integer"
1273 fromJSONKey = FromJSONKeyTextParser $ parseIntegralText "Integer"
1274
1274
1275instance FromJSON Natural where
1275instance FromJSON Natural where
1276− parseJSON = withScientific "Natural" $ \s ->
1276+ parseJSON value = do
1277− if Scientific.coefficient s < 0
1277+ integer :: Integer <- parseIntegral "Natural" value
1278+ if integer < 0 then
1278− then fail $ "Expected a Natural number but got the negative number: " <> show s
1279+ fail $ "expected Natural, encountered negative number " <> show integer
1279− else pure $ truncate s
1280+ else
1281+ pure $ fromIntegral integer
1280
1282
1281instance FromJSONKey Natural where
1283instance FromJSONKey Natural where
1282− fromJSONKey = FromJSONKeyTextParser $ \t -> parseScientificText t >>= \s ->
1284+ fromJSONKey = FromJSONKeyTextParser $ \text -> do
1283− if Scientific.coefficient s < 0
1285+ integer :: Integer <- parseIntegralText "Natural" text
1286+ if integer < 0 then
1284− then fail $ "Expected a Natural number but got the negative number: " <> show s
1287+ fail $ "expected Natural, encountered negative number " <> show integer
1285− else pure $ truncate s
1288+ else
1289+ pure $ fromIntegral integer
1286
1290
1287instance FromJSON Int8 where
1291instance FromJSON Int8 where
1288 parseJSON = parseBoundedIntegral "Int8"
1292 parseJSON = parseBoundedIntegral "Int8"
changelog.md+3
@@ -3,6 +3,9 @@ For the latest version of this document, please see [https://github.com/bos/aeso
3## Upcoming
3## Upcoming
4
4
5* Add `FromJSON` and `ToJSON` instances for `DiffTime`, thanks to Víctor López Juan
5* 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".
6
9
7## 1.2.1.0
10## 1.2.1.0
8
11
tests/ErrorMessages.hs+14
@@ -12,6 +12,7 @@ import Prelude.Compat
12import Data.Aeson (FromJSON(..), eitherDecode)
12import Data.Aeson (FromJSON(..), eitherDecode)
13import Data.Proxy (Proxy(..))
13import Data.Proxy (Proxy(..))
14import Instances ()
14import Instances ()
15+import Numeric.Natural (Natural)
15import Test.Framework (Test)
16import Test.Framework (Test)
16import Test.Framework.Providers.HUnit (testCase)
17import Test.Framework.Providers.HUnit (testCase)
17import Test.HUnit (Assertion, assertFailure, assertEqual)
18import Test.HUnit (Assertion, assertFailure, assertEqual)
@@ -22,6 +23,8 @@ tests :: [Test]
22tests =
23tests =
23 [
24 [
24 testCase "Int" int
25 testCase "Int" int
26+ , testCase "Integer" integer
27+ , testCase "Natural" natural
25 , testCase "String" string
28 , testCase "String" string
26 , testCase "HashMap" hashMap
29 , testCase "HashMap" hashMap
27 ]
30 ]
@@ -34,6 +37,17 @@ int = do
34 t "{}" $ expected "Int" "Object"
37 t "{}" $ expected "Int" "Object"
35 t "null" $ expected "Int" "Null"
38 t "null" $ expected "Int" "Null"
36
39
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+
37string :: Assertion
51string :: Assertion
38string = do
52string = do
39 let t = test (Proxy :: Proxy String)
53 let t = test (Proxy :: Proxy String)