Created
February 6, 2020 11:02
-
-
Save kremovtort/2a85607888c6af2bfa0ec9116847ba71 to your computer and use it in GitHub Desktop.
Partial JSON parsing/encoding with only needed for program fields.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE AllowAmbiguousTypes #-} | |
{-# LANGUAGE DataKinds #-} | |
{-# LANGUAGE DeriveAnyClass #-} | |
{-# LANGUAGE DeriveGeneric #-} | |
{-# LANGUAGE DuplicateRecordFields #-} | |
{-# LANGUAGE FlexibleContexts #-} | |
{-# LANGUAGE NoMonomorphismRestriction #-} | |
{-# LANGUAGE TypeApplications #-} | |
import Control.Lens | |
import Data.Aeson | |
import Data.ByteString.Lazy | |
import Data.Either (fromRight) | |
import Data.Foldable | |
import Data.Generics.Product | |
import Data.Generics.Sum | |
import GHC.Generics | |
data Partial a = | |
Partial | |
{ use :: a | |
, rest :: Value | |
} | |
deriving (Generic, Eq, Show) | |
instance FromJSON a => FromJSON (Partial a) where | |
parseJSON v = flip Partial v <$> parseJSON v | |
instance ToJSON a => ToJSON (Partial a) where | |
toJSON (Partial a rest) = | |
case toJSON a of | |
Object ob -> | |
case rest of | |
Object rob -> Object (ob <> rob) | |
_ -> Object ob | |
other -> other | |
data Foo = | |
Foo | |
{ a :: Integer | |
, b :: String | |
} | |
deriving (Generic, ToJSON, FromJSON, Show) | |
data Foo1 = | |
Foo1 | |
{ a :: Integer | |
, b :: String | |
, z :: [Int] | |
} | |
deriving (Generic, ToJSON, FromJSON, Show) | |
data Foo2 = | |
Foo2 | |
{ a :: Integer | |
, b :: String | |
, x :: Double | |
} | |
deriving (Generic, ToJSON, FromJSON, Show) | |
decodeIO :: FromJSON a => ByteString -> IO a | |
decodeIO = either fail pure . eitherDecode | |
main :: IO () | |
main = do | |
let foo1 = Foo1 {a = 1, b = "lol", z = [1, 2, 3]} | |
foo2 = Foo2 {a = 10, b = "kek", x = 0.5} | |
foo1a <- decodeIO @(Partial Foo) $ encode foo1 | |
foo2a <- decodeIO @(Partial Foo) $ encode foo2 | |
foo1' <- decodeIO @Foo1 $ encode $ updateFoo foo1a | |
foo2' <- decodeIO @Foo2 $ encode $ updateFoo foo2a | |
print foo1 | |
print foo1 | |
print foo1' | |
print foo2' | |
where | |
updateFoo :: Partial Foo -> Partial Foo | |
updateFoo = field @"use" . field @"b" %~ ("updated " <>) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment