首页 > 解决方案 > 如何使用镜头“重新排列”Aeson.Object?

问题描述

每当我伸手去拿镜头来转换一些 JSON 时,我似乎总是被卡住。

将其解析为Aeson.Value...

{
  "action": {
    "action": "reply",
    "replies": [
      "Does this work?",
      "What about this?"
    ]
  },
  "suggestions": [...],
  "inputs": [...]
}

...我正在尝试将其转换为...

{
  "action": "reply",
  "replies": [
    "Does this work?",
    "What about this?"
  ]
  "suggestions": [...],
  "inputs": [...]
}

基本上,我试图将嵌套在顶层 -key 内的所有键值对action带到顶层本身,最后删除顶层action键。action(注意,顶级键内有一个嵌套键action——这不是错字)。

标签: haskellhaskell-lensaeson

解决方案


使用lens-aeson包装中的镜头,我猜你想要的是这样的:

Object $ (x ^. _Object & sans "action") <> (x ^. key "action"._Object)

在这里,sans来自Control.Lens.At并移除顶层"action",留下一个Object(即,HashMap Text Value)与剩余的顶层键。getter选择key "action"._Object顶级"action"值并提取一个Object. 这两个Objects 可以使用构造函数连接并<>包装成 a 。ValueObject

完整代码:

{-# LANGUAGE OverloadedStrings #-}

module AesonLens where

import Data.Aeson
import Data.Aeson.Lens     -- from lens-aeson
import Control.Lens

ex1 :: IO Value
ex1 = do Just val <- decodeFileStrict "aesonlens.json"
         return val

main = do
  x <- ex1
  print $ Object $ (x ^. _Object & sans "action") <> (x ^. key "action"._Object)

带输入文件"aesonlens.json"

{
  "action": {
    "action": "reply",
    "replies": [
      "Does this work?",
      "What about this?"
    ]
  },
  "suggestions": [1,2,3],
  "inputs": [4,5,6]
}

产量:

> main
Object (fromList [("inputs",Array [Number 4.0,Number 5.0,Number 6.0]),
("action",String "reply"),("replies",Array [String "Does this work?",
String "What about this?"]),("suggestions",Array [Number 1.0,Number 2.0,
Number 3.0])])

推荐阅读