aeson-flatten (empty) → 0.1.0.0
raw patch · 6 files changed
+174/−0 lines, 6 filesdep +aesondep +aeson-flattendep +basesetup-changed
Dependencies added: aeson, aeson-flatten, base, bytestring, hspec, text, unordered-containers
Files
- LICENSE +30/−0
- README.md +17/−0
- Setup.hs +2/−0
- aeson-flatten.cabal +40/−0
- src/Data/Aeson/Flatten.hs +53/−0
- test/Spec.hs +32/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Author name here (c) 2016++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Author name here nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,17 @@+# aeson-prefix++JSON flatten for [Aeson](https://hackage.haskell.org/package/aeson).++See [hackage.haskell.org](https://hackage.haskell.org/package/aeson-flatten) for details.++## Installation++Run either `cabal install` or `stack install`. This is library, thus there is no executable available.++## Running tests++Tests can be run via `stack test`.++## Discalmer++Any feedback is very welcomed.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ aeson-flatten.cabal view
@@ -0,0 +1,40 @@+name: aeson-flatten+version: 0.1.0.0+synopsis: JSON flatten for Aeson+description: Please see README.md+homepage: https://github.com/githubuser/aeson-flatten#readme+license: BSD3+license-file: LICENSE+author: Jiri Marsicek+maintainer: jiri.marsicek@gmail.com+copyright: 2016 Jiri Marsicek+category: Web, Text, JSON+build-type: Simple+extra-source-files: README.md+cabal-version: >=1.10++library+ hs-source-dirs: src+ exposed-modules: Data.Aeson.Flatten+ build-depends: base >= 4.7 && < 5+ , aeson+ , text+ , unordered-containers+ ghc-options: -Wall+ default-language: Haskell2010++test-suite aeson-flatten-test+ type: exitcode-stdio-1.0+ hs-source-dirs: test+ main-is: Spec.hs+ build-depends: base+ , aeson+ , aeson-flatten+ , bytestring+ , hspec+ ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall+ default-language: Haskell2010++source-repository head+ type: git+ location: https://github.com/githubuser/aeson-flatten
+ src/Data/Aeson/Flatten.hs view
@@ -0,0 +1,53 @@+-- |+-- Module: Data.Aeson.Prefix+-- Maintainer: Jiri Marsicek <jiri.marsicek@gmail.com>+--+-- Module provides 'flatten' which is used to flatten structure of 'Data.Aeson' JSON 'Value' as much as possible.+--+-- == Examples+--+-- === Basic objects+--+-- @{ "a": { "b": 1 } }@ results in @{ "b": 1 }@+--+-- @{ "a": { "b": { "c": 1 } } }@ results in @{ "c": 1 }@+--+-- @{ "a": [ { "b": { "c": 1 } }, { "b": { "c": 2 } } ] }@ results in @{ "a": [ { "c": 1 }, { "c": 2 } ] }@+--+-- === Name conflicts result in data loss+--+-- @{ "a": 1, "b": { "a": 2 } }@ results in @{ "a": 1 }@+--+-- * I don't know yet whether this is a feature or a bug :)+module Data.Aeson.Flatten+ ( flatten+ -- * Utility functions+ , isObject+ , mergeTo+ ) where++import Data.Aeson (Value(..))+import Data.Foldable (foldl')+import qualified Data.HashMap.Strict as Map (elems, filter, union)++-- |+-- Predicate for testing whether provided 'Value' is a 'Object'.+isObject :: Value -> Bool+isObject (Object _) = True+isObject _ = False++-- |+-- Merges keys from second 'Value' to first 'Value'.+-- In case of name conflict, values from first are preserved.+mergeTo :: Value -> Value -> Value+mergeTo (Object o1) (Object o2) = Object $ Map.union o1 o2+mergeTo o _ = o++-- |+-- Recursively Flattens the structure of the provided JSON 'Value'+flatten :: Value -> Value+flatten (Array a) = Array $ flatten <$> a+flatten (Object o) = let flat = flatten <$> o+ rest = Map.filter (not . isObject) flat+ in foldl' mergeTo (Object rest) $ Map.elems flat+flatten v = v
+ test/Spec.hs view
@@ -0,0 +1,32 @@+{-# LANGUAGE OverloadedStrings #-}+import Test.Hspec++import Data.Aeson+import Data.Aeson.Flatten+import Data.Maybe (fromJust)+import Data.ByteString (ByteString)++decodeExample :: ByteString -> Value+decodeExample = fromJust . decodeStrict'++shouldResultIn :: ByteString -> ByteString -> Expectation+shouldResultIn input output = flatten (decodeExample input) `shouldBe` flatten (decodeExample output)++-- Test Cases++main :: IO ()+main = hspec $+ describe "Data.Aeson.Flatten" $+ describe "flatten" $ do+ it "works for empty object" $+ "{}" `shouldResultIn` "{}"+ it "works for simple object" $+ "{ \"a\": { \"b\": 1 } }" `shouldResultIn` "{ \"b\": 1 }"+ it "preserves values from more significant level in case of name clash" $+ "{ \"a\" : { \"b\": 1 }, \"b\": 2 }" `shouldResultIn` "{ \"b\": 2 }"+ it "works for one level flattening" $+ "{ \"a\": { \"b\": 1, \"c\": 2 } }" `shouldResultIn` "{ \"b\": 1, \"c\": 2 }"+ it "works for two level flattening" $+ "{ \"a\": { \"b\": { \"c\": 1 } } }" `shouldResultIn` "{ \"c\": 1 }"+ it "works for array with one level objects" $+ "{ \"a\": [ { \"b\": { \"c\": 1 } }, { \"b\": { \"c\": 234 } } ] }" `shouldResultIn` "{ \"a\": [ { \"c\": 1 }, { \"c\": 234 } ] }"