我正在解析一些我无法控制的数据。我的值是一个字符串数组。它们可以是普通字符串,数字的字符串表示形式,也可以是带引号的数字。
["This is just a string", "\"5\"", "3"]
我想编写一个函数toValue
,将它们转换为适当的类型以转换为JSON。
toValue :: (ToJSON a) => String -> a
toValue (if a number) = parseInt
toValue (if a quoted number) = parseInt . stripQuotes
toValue _ = id
我想删除引号,如果它是一个被引号括起来的数字,然后将其转换为数字(如果是数字),否则将其作为字符串传回。
我可以使用模式匹配吗?其他一些方式?
答案 0 :(得分:3)
import Data.Char
import Data.Bool
parse a@('"':n:'"':[]) = bool (Left a) (Right (read [n] :: Int)) (isNumber n)
parse a@('"':n:m:'"':[]) = bool (Left a) (Right (read [n,n] :: Int)) (isNumber n && isNumber m)
parse a@(n:[]) = bool (Left a) (Right (read [n] :: Int)) (isNumber n)
parse a@(n:m:[]) = bool (Left a) (Right (read [n,n] :: Int)) (isNumber n && isNumber m)
parse xs = Left xs
> map parse ["This is just a string", "\"5\"", "3"]
[Left "This is just a string",Right 5,Right 3]
然后,您可以使用either
模块中的Data.Either
函数将数字(权限)和字符串(Lefts)编码为JSON。
答案 1 :(得分:-1)
正如你所提议的那样编写一个函数toValue :: ToJSON a => String -> a
并不是那么难:让我们简单地让toValue
成为类ToJSON
的方法
class ToJSON a where
toValue :: String -> a
然后将Int
的实例定义为
instance ToJSON Int where
toValue s@('\"' : _) = read (read s) -- with quotes
toValue s = read s -- without quotes
String
的实例稍微复杂一些(因为String
是[Char]
的同义词),但绝不是火箭科学:
class ToJSONList a where
toValues :: String -> [a]
instance ToJSONList Char where
toValues = id
instance ToJSONList a => ToJSON [a] where
toValue = toValues
现在,在交互式会话中测试它,我们有:
> toValue "This is just a string" :: String
"This is just a string"
> toValue "\"5\"" :: Int
5
> toValue "3" :: Int
3
但是,从您的问题来看,似乎您有一个用例toValue
不能很好地支持的用例,即将列表的所有元素转换为适当的JSON表示。为此,您可能希望引入用于表示JSON值的代数数据类型:
data JSON = JInt Int | JString String deriving Show
然后使用函数toJSON将字符串转换为最合适的JSON表示形式:
toJSON :: String -> JSON
toJSON s =
case reads s of
[(n, "")] -> JInt n -- Int, no quotes
_ -> case reads s of
[(s, "")] -> case reads s of
[(n, "")] -> JInt n -- Int, quotes
_ -> JString s -- String, quotes
_ -> JString s -- String, no quotes
实际上,为了回答你问题的这一部分,这个函数只是通过(嵌套)模式匹配来定义。但是,如果你需要解析的语法(语法)变得更复杂,那么只需要整数文字,引用的整数文字和字符串文字,这种定义解析器的方式很快变得笨拙且容易出错,你可能想要开始然后查看parser combinators或parser generators。
对于JSON值的简单语言,这可以说仍然很好。以下是交互式会话中的一个简单示例:
> map toJSON ["This is just a string", "\"5\"", "3"]
[JString "This is just a string",JInt 5,JInt 3]