Как «переставить» Aeson.Object с помощью линз? - PullRequest
0 голосов
/ 18 февраля 2020

Кажется, я все время застреваю всякий раз, когда берусь за линзы, чтобы преобразовать некоторые 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": [...]
}

По существу Я пытаюсь перенести все пары ключ-значение, вложенные в ключ action верхнего уровня, на сам верхний уровень и, наконец, удалить ключ action верхнего уровня. (Обратите внимание, что внутри ключа action верхнего уровня есть вложенная клавиша action - это не опечатка).

1 Ответ

3 голосов
/ 18 февраля 2020

Используя линзы из пакета lens-aeson, я думаю, что вам нужно что-то вроде:

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

Здесь sans происходит от Control.Lens.At и удаляет верхний уровень "action", оставляя Object (т.е. HashMap Text Value) с оставшимися клавишами верхнего уровня. Получатель key "action"._Object выбирает значение "action" верхнего уровня и извлекает Object. Два Object можно объединить с помощью <> и обернуть в Value с помощью конструктора Object.

Полный код:

{-# 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])])
...