Aeson Кодирование вложенных записей - PullRequest
1 голос
/ 07 февраля 2020

Предположим, есть эта запись:

data Place = Place
  { details :: PlaceDetails
  , amenities :: [Amenity]
  , photos :: [PlacePhoto]
  } deriving (Generic)

Я реализовал toEncoding для каждого типа данных, но я хотел бы объединить эти поля в типе Place. На данный момент это выглядит так:

instance ToJSON Place where
  toEncoding Place{..} = 
    pairs  $ "details" .= details
          <> "amenities" .= amenities
          <> "photos" .= photos

Я использую toEncoding, чтобы сохранить определенный порядок, который я хочу. Однако я хотел бы удалить этот ключ details из кодировки, чтобы все поля из PlaceDetails находились на одном уровне с amenities и photos, без указания всех этих полей вручную, например PlaceDetails довольно большой. Как бы я это сделал? Я знаю, что могу объединить [Value], используя HML.unions, но мне удалось сделать это только с toJSON, а не toEncoding.

То, что у меня сейчас есть:

{
    "details": {
        "id": "place_6de6cda0f8524a6f9c264c84afdbadad",
        "name":"somename",
        "description":"some description", 
        "other": "a lot more fields"
    }
    "amenities": []
    "photos": []
}

Вот что я хочу:

{
    "id":"place_6de6cda0f8524a6f9c264c84afdbadad",
    "name":"somename",
    "description":"some description", 
    "other": "a lot more fields",
    "amenities": []
    "photos": []
}

Спасибо.

1 Ответ

1 голос
/ 07 февраля 2020

Объект Aeson - это просто хэш-карта, которую можно объединить, используя <> (инфикс) или mappend.

Например:

#!/usr/bin/env cabal
{- cabal:
    build-depends: base, aeson
-}
{-# LANGUAGE DeriveAnyClass    #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE OverloadedLists   #-}
{-# LANGUAGE DeriveGeneric     #-}
{-# LANGUAGE RecordWildCards   #-}

module Main where

import Data.Aeson
import GHC.Generics

main :: IO ()
main = print (encode (Place (Foo 1 2) (Bar 3 4)))

data Foo = Foo {foo1 :: Int, foo2 :: Int}
    deriving (Eq,Ord,Show,Generic,ToJSON)

data Bar = Bar {bar1 :: Int, bar2 :: Int}
    deriving (Eq,Ord,Show,Generic,ToJSON)

data Place = Place { foo :: Foo , bar :: Bar }
    deriving (Eq,Ord,Show,Generic)

instance ToJSON Place where
  toJSON Place{..} =
       let Object b = toJSON bar
       in Object ([("foo",toJSON foo)] <> b)

И мы можем запустить это:

% chmod +x so.hs && ./so.hs
... snippet out build info ...
"{\"bar1\":3,\"foo\":{\"foo2\":2,\"foo1\":1},\"bar2\":4}"
...