opened
amigalemming
username_0
I find the parsing of nested JSON structures in [Elm](http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Json-Decode) somehow simpler than the way `aeson` goes. In Elm I start with simple `field` parsers and build them together using `liftAn` style combinators. No need to define instances. Maybe the `lens` stuff in #570 addresses this style, but it looks complicated.
Elm style JSON parsing
issue
created
bergmark
username_1
Elm has to do it this way since there are no type classes. The disadvantage with the approach is that you essentially have to pass around the type class dictionaries manually instead of having the compiler insert them for you. With deeply nested structures this becomes cumbersome, even morey so when recursion or polymorphism comes into the picture.

The good news is that you can always translate the aeson approach to the one used in elm:
```
string2Json :: String -> Value
string2Json = toJson

myString2Json :: MyString -> Value
myString2Json (MyString s) = string2Json s

int2Json :: Int -> Value
int2Json = toJson

tuple2Json :: (a -> Value) -> (b -> Value) -> ((a, b) -> Value)
tuple2Json a2Json b2Json (a,b) = toJson (a2Json a, a2json b)

myStringInt2Json = tuple2Json myString2Json int2Json
```
comment
created
amigalemming
username_0
I meant parsing, not formatting JSON.
comment
created
Lysxia
username_2
+1 on this proposal.

Dictionaries have to be passed anyway, whether implicitly (aeson) or explicitly (Elm). However with type classes this essentially means you need to declare one type for every dictionary. So the type-class-based approach of aeson works best when types match the JSON schema closely. Extra combinators would be handy in less ideal situations; e.g. when your type is a single flat record  represented in JSON by nested objects.
comment
created
phadej
username_3
There'is (almost) everything you need to do Elm style parsing.

```haskell
data Foo = Foo
    { fooBool :: Bool
    , fooInt :: Int
    }

boolParseJSON :: Value -> Parser Bool
boolParseJSON = parseJSON

intParseJSON :: Value -> Parser Int
intParseJSON = parseJSON

fooParseJSON :: Value -> Parser Foo
fooParseJSON = withObject "Foo" $ \obj -> Foo
    <$> explicitParseField boolParseJSON obj "bool"
    <$> explicitParseField intParseJSON obj "int"

decodeFoo :: LBS.ByteString -> Either Strict Foo
decodeFoo bs = eitherDecode bs >>= resultToEither . parseEither fooParseJSON
  where
    -- this could be added to `aeson`
    resultToEither :: Result a -> Either String a 
    resultToEither (Success a) = Right a   
    resultToEither (Error str) = Left str

    -- or/and this
    -- analogue of 'either'
    result :: (String -> r) -> (a - > r) -> Result a -> r
    result s _ (Success x) = s x
    result _ e (Error x)   = e x
```
comment
created
Lysxia
username_2
Oh, I didn't see the `explicitParseField`!
comment
created
bergmark
username_1
In general any type class method can be transformed into a function with explicit arguments instead of dictionaries.


I think the best way to start out this process would be to create another library on top of aeson so that it can mature freely. If there are any show-stoppers for this in aeson I'd be all for fixing those.
comment
created
bergmark
username_1
Closing this as it doesn't need to be done in aeson itself, is someone writes a separate library for this we may at some point consider moving it into aeson proper.
comment
closed
bergmark
username_1
issue