Как переставить объект Aeson.Object с помощью линз?

Кажется, я сохраняю застревать, когда я обращаюсь за линзами, чтобы преобразовать какой-нибудь JSON.

После синтаксического анализа этого в _1 _...

{
  "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 ключ - это не опечатка).


person Saurabh Nanda    schedule 18.02.2020    source источник


Ответы (1)


Используя линзы из пакета 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])])
person K. A. Buhr    schedule 18.02.2020
comment
IIUC, это не действительно работает на Aeson.Value. Основные операции выполняются с базовым HashMap, и в конце он преобразуется обратно в Aeson.Value с помощью конструктора Aeson.Object. Верно? - person Saurabh Nanda; 30.03.2020
comment
Что, если бы Aeson.Value имел экземпляр В использование класса типов sans? Это сделало бы это более прямым, не так ли? - person Saurabh Nanda; 30.03.2020
comment
Кроме того, есть ли простой способ найти оператора объектива, который выполняет X? Например, как вы узнали об операторе sans? Последующий вопрос может заключаться в следующем: существует ли оператор объектива для добавления ключа / значения в структуру данных, подобную карте? т.е. противоположность sans? - person Saurabh Nanda; 30.03.2020