help understanding JSON

I have some JSON which looks like this: {"count":2, "result":[{"LastTrade":"31.24", "Symbol":"FOO"}, {"LastTrade":"345.12", "Symbol":"BAR"}]} (named testQuoteResult below) When I try to parse this into types defined below it failed because the Double is encoded as a String. If I change the type of LastTrade in my code to String everything is ok but I am left read'ing the String. I have defined the following using Language.JsonGrammar: import Data.Iso import Language.JsonGrammar import Prelude hiding (id, (.), head, either) import Control.Category ((.)) import qualified Data.Aeson as JS import qualified Data.ByteString.Char8 as BS import qualified Data.Attoparsec as P data MyQuote = MyQuote { price :: Double, symbol :: String } deriving(Show) myQuote = $(deriveIsos ''MyQuote) instance Json MyQuote where grammar = myQuote . object ( prop "LastTrade" . prop "Symbol" ) data MyQuoteResult = MyQuoteResult { count :: Int, result :: [MyQuote] } deriving(Show) myQuoteResult = $(deriveIsos ''MyQuoteResult) instance Json MyQuoteResult where grammar = myQuoteResult . object ( prop "count" . prop "result" ) tryJSON input = case P.parse JS.json (BS.pack input) of P.Done s v -> Right v other -> Left ("failed parse " ++ show other) Using it like this:
let Right qr = tryJSON testQuoteResult fromJson qr :: Maybe MyQuoteResult Nothing
Is there some way to convince the JSON text parser to turn "12.34" into (Double 12.34)?? An example using pure aeson would be fine if required. I just decided to play with JsonGrammar since it was announced today and it sounded interesting.

Hello, I do not have the right answer for your question, I am just starting to learn Haskell. Still, you may want to take a look at the JSON library example described in real world Haskell, this can bring you some more clues: http://book.realworldhaskell.org/read/writing-a-library-working-with-json-da... Regards, Adrien On Tue, 10 May 2011 00:51:30 -0700, Sean Perry wrote:
I have some JSON which looks like this:
{"count":2, "result":[{"LastTrade":"31.24", "Symbol":"FOO"}, {"LastTrade":"345.12", "Symbol":"BAR"}]} (named testQuoteResult below)
When I try to parse this into types defined below it failed because the Double is encoded as a String. If I change the type of LastTrade in my code to String everything is ok but I am left read'ing the String.
I have defined the following using Language.JsonGrammar:
import Data.Iso import Language.JsonGrammar import Prelude hiding (id, (.), head, either) import Control.Category ((.))
import qualified Data.Aeson as JS import qualified Data.ByteString.Char8 as BS import qualified Data.Attoparsec as P
data MyQuote = MyQuote { price :: Double, symbol :: String } deriving(Show)
myQuote = $(deriveIsos ''MyQuote)
instance Json MyQuote where grammar = myQuote . object ( prop "LastTrade" . prop "Symbol" )
data MyQuoteResult = MyQuoteResult { count :: Int,
result :: [MyQuote] } deriving(Show)
myQuoteResult = $(deriveIsos ''MyQuoteResult)
instance Json MyQuoteResult where grammar = myQuoteResult . object ( prop "count" . prop "result" )
tryJSON input = case P.parse JS.json (BS.pack input) of P.Done s v -> Right v other -> Left ("failed parse " ++ show other)
Using it like this:
let Right qr = tryJSON testQuoteResult fromJson qr :: Maybe MyQuoteResult Nothing
Is there some way to convince the JSON text parser to turn "12.34" into (Double 12.34)??
An example using pure aeson would be fine if required. I just decided to play with JsonGrammar since it was announced today and it sounded interesting.
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

Thanks Adrien. In that chapter they actually explicitly define all JS numbers to be Double and later in the Parsec chapter their parser reads the Strings into Floats directly. I was looking for a way to use the library provided parsers rather than crafting my own. Sure it is not much code but why rewrite what others have already tested?
Mostly this boils down to a complete lack of useful docs. A laundry list of functions is not always helpful. At least we could mimic the Python docs and add examples.
On May 10, 2011, at 1:05, Adrien Haxaire
Hello,
I do not have the right answer for your question, I am just starting to learn Haskell.
Still, you may want to take a look at the JSON library example described in real world Haskell, this can bring you some more clues:
http://book.realworldhaskell.org/read/writing-a-library-working-with-json-da...
Regards, Adrien
On Tue, 10 May 2011 00:51:30 -0700, Sean Perry wrote:
I have some JSON which looks like this:
{"count":2, "result":[{"LastTrade":"31.24", "Symbol":"FOO"}, {"LastTrade":"345.12", "Symbol":"BAR"}]} (named testQuoteResult below)
When I try to parse this into types defined below it failed because the Double is encoded as a String. If I change the type of LastTrade in my code to String everything is ok but I am left read'ing the String.
I have defined the following using Language.JsonGrammar:
import Data.Iso import Language.JsonGrammar import Prelude hiding (id, (.), head, either) import Control.Category ((.))
import qualified Data.Aeson as JS import qualified Data.ByteString.Char8 as BS import qualified Data.Attoparsec as P
data MyQuote = MyQuote { price :: Double, symbol :: String } deriving(Show)
myQuote = $(deriveIsos ''MyQuote)
instance Json MyQuote where grammar = myQuote . object ( prop "LastTrade" . prop "Symbol" )
data MyQuoteResult = MyQuoteResult { count :: Int,
result :: [MyQuote] } deriving(Show)
myQuoteResult = $(deriveIsos ''MyQuoteResult)
instance Json MyQuoteResult where grammar = myQuoteResult . object ( prop "count" . prop "result" )
tryJSON input = case P.parse JS.json (BS.pack input) of P.Done s v -> Right v other -> Left ("failed parse " ++ show other)
Using it like this:
let Right qr = tryJSON testQuoteResult fromJson qr :: Maybe MyQuoteResult Nothing
Is there some way to convince the JSON text parser to turn "12.34" into (Double 12.34)??
An example using pure aeson would be fine if required. I just decided to play with JsonGrammar since it was announced today and it sounded interesting.
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

Mostly this boils down to a complete lack of useful docs True, I faced problems with respect to functions in System.Posix.IO because of lack of proper docs.
On Tue, May 10, 2011 at 2:11 PM, Sean Perry
Thanks Adrien. In that chapter they actually explicitly define all JS numbers to be Double and later in the Parsec chapter their parser reads the Strings into Floats directly. I was looking for a way to use the library provided parsers rather than crafting my own. Sure it is not much code but why rewrite what others have already tested?
Mostly this boils down to a complete lack of useful docs. A laundry list of functions is not always helpful. At least we could mimic the Python docs and add examples.
On May 10, 2011, at 1:05, Adrien Haxaire
wrote: Hello,
I do not have the right answer for your question, I am just starting to learn Haskell.
Still, you may want to take a look at the JSON library example described in real world Haskell, this can bring you some more clues:
http://book.realworldhaskell.org/read/writing-a-library-working-with-json-da...
Regards, Adrien
On Tue, 10 May 2011 00:51:30 -0700, Sean Perry wrote:
I have some JSON which looks like this:
{"count":2, "result":[{"LastTrade":"31.24", "Symbol":"FOO"}, {"LastTrade":"345.12",
"Symbol":"BAR"}]}
(named testQuoteResult below)
When I try to parse this into types defined below it failed because the Double is encoded as a String. If I change the type of LastTrade in my code to String everything is ok but I am left read'ing the String.
I have defined the following using Language.JsonGrammar:
import Data.Iso import Language.JsonGrammar import Prelude hiding (id, (.), head, either) import Control.Category ((.))
import qualified Data.Aeson as JS import qualified Data.ByteString.Char8 as BS import qualified Data.Attoparsec as P
data MyQuote = MyQuote { price :: Double, symbol :: String } deriving(Show)
myQuote = $(deriveIsos ''MyQuote)
instance Json MyQuote where grammar = myQuote . object ( prop "LastTrade" . prop "Symbol" )
data MyQuoteResult = MyQuoteResult { count :: Int,
result :: [MyQuote] } deriving(Show)
myQuoteResult = $(deriveIsos ''MyQuoteResult)
instance Json MyQuoteResult where grammar = myQuoteResult . object ( prop "count" . prop "result" )
tryJSON input = case P.parse JS.json (BS.pack input) of P.Done s v -> Right v other -> Left ("failed parse " ++ show other)
Using it like this:
let Right qr = tryJSON testQuoteResult fromJson qr :: Maybe MyQuoteResult Nothing
Is there some way to convince the JSON text parser to turn "12.34" into (Double 12.34)??
An example using pure aeson would be fine if required. I just decided to play with JsonGrammar since it was announced today and it sounded interesting.
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
-- Regards Lakshmi Narasimhan T V

Sean Perry wrote:
I have some JSON which looks like this: {"count":2, "result":[{"LastTrade":"31.24", "Symbol":"FOO"}, {"LastTrade":"345.12", "Symbol":"BAR"}]} ...Is there some way to convince the JSON text parser to turn "12.34" into (Double 12.34)??
No, and rightly so. It is encoded as a string in the JSON itself, so that is the way the library should parse it. If you need to interpret certain strings in the JSON as encoded numbers, that is a separate step in your program logic and should be represented that way. People using languages that blur the lines between numbers and their string representation are often sloppy about their JSON design in this way. If you want, you can easily write a function sloppyJson :: Value -> Value which replaces string representations of numbers by numbers wherever possible. It might be useful sometimes. But not always - it certainly happens that certain fields happen to contain something that looks like a number but actually must remain a string. Usually the best practice is to convert the JSON Value to your own type-safe representation of the data, wrapping the result in Maybe (or a richer error type) to handle cases where the conversion from string fails.
Mostly this boils down to a complete lack of useful docs. A laundry list of functions is not always helpful.
Actually, it often is helpful in Haskell, because the type signatures of the functions are very eloquent. Here, the "json" function produces a value of type Parser Value. Clicking on "Parser" will get you complete instructions on how to use those (in this case it happens to be a Parser from the attoparsec package, which you will see immediately), and clicking on "Value" will get you complete instructions on how to use those once you have obtained them by parsing. Of course, you are right that it would be much better if the documentation would include at least a few words that give you a basic idea even before you click. But since all the information is actually there and easy to obtain in a standard way, you can understand why Haskell coders are often a bit too lazy about that. Regards, Yitz
participants (4)
-
Adrien Haxaire
-
lakshminaras2002@gmail.com
-
Sean Perry
-
Yitzchak Gale