使用haskell映射json数据

时间:2016-11-05 10:10:06

标签: json parsing haskell binary

我只是学习一个haskell,看起来一切都很好,即使可怕的monad对我来说也不是什么大问题。但我根本无法获得真实的实际内容。

我选择的第一个haskell实际任务如下: 给定一个JSON描述一些二进制文件的格式来解析该文件。

JSON有一些深层嵌套的结构,其中包含列表的关联列表(字典)列表,其中端点为数字或字符串。 首先,我希望能够映射其他那些端点(为jsons数据设置functor类),特别是将一些字符串转换为数字。同样能够折叠所有这些端点也是很好的。

我很容易想出一些python代码。但是与haskell无关。 那么你对haskell实现的建议是什么?听到一些最大程度上使用库的解决方案的建议真的很高兴,而不是从头开始编写所有东西。

提前致谢!

加入--- 我在python中的例子

一些辅助函数:

islist = lambda l: isinstance(l, collections.Iterable) and not isinstance(l, (str, bytes))
isdict = lambda d: isinstance(d, collections.Mapping)
isiter = lambda i: islist(i) or isdict(i)

def iterable(d):
    if isdict(d):
        i = d.items()
    elif islist(d):
        i = enumerate(d)
    else:
        raise ValueError
    return i

迭代嵌套json数据的迭代器:

def nested_iter(nested, f = lambda *args: None):
    for key, value in iterable(nested):
        if not isiter(value):
            f(nested, key)
            yield key, value
        else:
            yield from nested_iter(value, f)

现在我可以用键列表替换一些数字:

def list_from_num(d, k):
    if type(d[k]) == int:
        d[k] = [k]*d[k]
list(nested_iter(typedef, list_from_num))

或者我可以用一些其他具有相同键名的嵌套数据替换某些字符串

def nest_dicts(defs, d, k):
    if d[k] in defs.keys():
        d[k] = deepcopy(defs[d[k]])
        if isiter(d[k]):
            list(nested_iter(d[k], partial(nest_dicts, defs)))
list(nested_iter(typedef, partial(nest_dicts, typedef)))

或者可以展平数据

list(nested_iter(d))

解析二进制文件有点进化,但它只不过是向迭代器传递一个函数

1 个答案:

答案 0 :(得分:0)

这是我的解决方案。 它使用Control.Lens,Data.Aeson.Lens,Control.Lens.Plated

可以使用Uniplate或Lens.Plated转换来转换值。

例如用每个数字替换该数字长度的键值列表:

n2k :: T.Text -> Value -> Value --import qualified Data.Text as T
n2k s (Number x)
  | isInteger x = case toBoundedInteger x of
    Just n    -> Array (V.replicate n (String s)) -- import qualified Data.Vector as V
    _         -> Number x
  | otherwise =  Number x
n2k _ v = v

f (Object o) = Object $ imap n2k o --imap from Data.Map.Lens
f x          = x

j2 = transform f j --transform JSON j using function f

用具有相同键的数据替换字符串:

-- o is hashmap where we are looking for keys to substitute strings
h (String s) = fromMaybe (String s) (H.lookup s o) --import qualified Data.HashMap.Lazy as H
h x          = x

j2 = transform h j 

将所有数字都列入清单:

l = [x | Number x <- universe j]