Skip to content

Instantly share code, notes, and snippets.

@kremovtort
Created February 6, 2020 11:02
Show Gist options
  • Save kremovtort/2a85607888c6af2bfa0ec9116847ba71 to your computer and use it in GitHub Desktop.
Save kremovtort/2a85607888c6af2bfa0ec9116847ba71 to your computer and use it in GitHub Desktop.
Partial JSON parsing/encoding with only needed for program fields.
{-# 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