diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 Lucas David Traverso
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,1 @@
+# conferer-source-json
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/conferer-source-json.cabal b/conferer-source-json.cabal
new file mode 100644
--- /dev/null
+++ b/conferer-source-json.cabal
@@ -0,0 +1,66 @@
+cabal-version: 1.18
+
+-- This file has been generated from package.yaml by hpack version 0.33.0.
+--
+-- see: https://github.com/sol/hpack
+--
+-- hash: 75e351874fa593dd3d42bba9fbbe98f40ceb07b84a807ac0f020472cc07901d2
+
+name:           conferer-source-json
+version:        0.4.0.0
+synopsis:       conferer's source for reading json files
+
+description:    Library to abstract the parsing of many haskell config values from different config sources
+category:       Configuration
+homepage:       https://github.com/ludat/conferer#readme
+author:         Lucas David Traverso
+maintainer:     lucas6246@gmail.com
+copyright:      MIT
+license:        BSD3
+license-file:   LICENSE
+build-type:     Simple
+extra-doc-files:
+    README.md
+    LICENSE
+
+library
+  exposed-modules:
+      Conferer.Source.JSON
+  other-modules:
+      Paths_conferer_source_json
+  hs-source-dirs:
+      src
+  default-extensions: OverloadedStrings LambdaCase QuasiQuotes ScopedTypeVariables
+  build-depends:
+      aeson >=0.10 && <2.0
+    , base >=4.3 && <5
+    , bytestring >=0.10 && <0.11
+    , conferer >=0.4.0.0 && <0.5.0.0
+    , directory >=1.2 && <2.0
+    , text >=1.1 && <1.3
+    , unordered-containers
+    , vector
+  default-language: Haskell2010
+
+test-suite specs
+  type: exitcode-stdio-1.0
+  main-is: Spec.hs
+  other-modules:
+      Conferer.Source.JSONSpec
+      Paths_conferer_source_json
+  hs-source-dirs:
+      test
+  default-extensions: OverloadedStrings LambdaCase QuasiQuotes ScopedTypeVariables
+  build-depends:
+      aeson >=0.10 && <2.0
+    , aeson-qq
+    , base >=4.3 && <5
+    , bytestring >=0.10 && <0.11
+    , conferer
+    , conferer-source-json
+    , directory >=1.2 && <2.0
+    , hspec
+    , text >=1.1 && <1.3
+    , unordered-containers
+    , vector
+  default-language: Haskell2010
diff --git a/src/Conferer/Source/JSON.hs b/src/Conferer/Source/JSON.hs
new file mode 100644
--- /dev/null
+++ b/src/Conferer/Source/JSON.hs
@@ -0,0 +1,121 @@
+module Conferer.Source.JSON
+  (
+  -- * How to use this source
+  -- | As any other source you can add it to a config using the 'addSource'
+  -- function. There are a couple of oddities that come from supporting many
+  -- different sources which do not support numbers, arrays or objects
+  -- nativelly
+  --
+  -- @
+  -- import 'Conferer'
+  -- import Conferer.Source.JSON ('mkJsonSource')
+  --
+  -- main = do
+  --   config <-
+  --     'defaultConfig' \"awesomeapp\"
+  --     & 'addSource' 'mkJsonSource'
+  --   warpSettings <- 'getFromConfig' \"warp\" config
+  --   runSettings warpSettings application
+  -- @
+  --
+  -- This will result on a source that upon starting looks the file
+  -- @config/{.env}.json@ in the current directory and uses it to provide config
+  -- keys.
+  --
+  -- TODO Describe how we transform json into key value strings
+  mkJsonSource
+  , mkJsonSource'
+
+  -- * Internal utility functions
+  -- | These may be useful for someone but are subject to change at any point so
+  -- use with care
+  , traverseJSON
+  , resultToMaybe
+  , valueToText
+  , boolToString
+  )
+where
+
+import           Data.Aeson
+import qualified Data.HashMap.Strict as HashMap
+import           Data.Text (Text)
+import qualified Data.Text as Text
+import qualified Data.Text.Encoding as Text
+import           Data.Vector
+import           Text.Read (readMaybe)
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as L
+import           System.Directory (doesFileExist)
+import           Data.Monoid
+
+
+import Conferer.Source.Files
+import Conferer.Source.Null
+import Conferer.Types
+
+-- | Default 'SourceCreator' which usese files with @config/{env}.json@
+-- template, if the file is not present it will behave like the null source
+-- (it has no keys) but if the file doesn't have valid json it will throw an
+-- error
+mkJsonSource :: SourceCreator
+mkJsonSource config = do
+  fileToParse <- getFilePathFromEnv config "json"
+  fileExists <- doesFileExist fileToParse
+  if fileExists
+    then do
+      value <- decodeStrict' <$> B.readFile fileToParse
+      case value of
+        Nothing ->
+          error $ "Failed to decode file '" <> fileToParse <> "'"
+        Just v -> do
+          mkJsonSource' v config
+    else do
+      mkNullSource config
+
+-- | Just like 'mkJsonSource' but accepts the json value as a parameter
+mkJsonSource' :: Value -> SourceCreator
+mkJsonSource' v = \_config ->
+  return $ Source
+  { getKeyInSource = \k -> do
+      return $ traverseJSON k v
+  }
+
+-- | Traverse a 'Value' using a 'Key' to get a value for conferer ('Text').
+--
+-- This function can nest objects and arrays when keys are nested
+--
+-- @
+-- 'traverseJSON' "a.b" {a: {b: 12}} == Just "12"
+-- 'traverseJSON' "a.b" {a: {b: false}} == Just "false"
+-- 'traverseJSON' "a" {a: {b: false}} == Nothing
+-- 'traverseJSON' "1" [false, true] == Just "true"
+-- 'traverseJSON' "0.a" [{a: "hi"}] == Just "hi"
+-- 'traverseJSON' "0" [] == Nothing
+-- @
+traverseJSON :: Key -> Value -> Maybe Text
+traverseJSON (Path []) v = valueToText v
+traverseJSON (Path (k:ks)) (Object o) =
+  HashMap.lookup k o >>= traverseJSON (Path ks)
+traverseJSON (Path (k:ks)) (Array vs) = do
+  n :: Int <- readMaybe $ Text.unpack k
+  value <- vs !? n
+  traverseJSON (Path ks) value
+traverseJSON (Path _) _ = Nothing
+
+valueToText :: Value -> Maybe Text
+valueToText (String t) = Just t
+valueToText (Object _o) = Nothing
+valueToText (Array _as) = Nothing
+valueToText (Number n) = Just $ Text.decodeUtf8 $ L.toStrict $ encode $ Number n
+valueToText (Bool b) = Just $ boolToString b
+valueToText (Null) = Nothing
+
+boolToString :: Bool -> Text
+boolToString True = "true"
+boolToString False = "false"
+
+-- | Because we use an old version of 'aeson'
+resultToMaybe :: Result a -> Maybe a
+resultToMaybe (Error _) = Nothing
+resultToMaybe (Success a) = Just a
+
diff --git a/test/Conferer/Source/JSONSpec.hs b/test/Conferer/Source/JSONSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Conferer/Source/JSONSpec.hs
@@ -0,0 +1,59 @@
+module Conferer.Source.JSONSpec where
+
+import Data.Aeson.QQ
+import Test.Hspec
+
+import Conferer
+import Conferer.Source.JSON
+
+spec :: Spec
+spec = do
+  describe "json source" $ do
+    it "getting an existing path returns the right value" $ do
+      c <- emptyConfig
+           & addSource (mkJsonSource' [aesonQQ| {"postgres": {"url": "some url", "ssl": true}} |])
+      res <- getKey "postgres.url" c
+      res `shouldBe` Just "some url"
+
+    it "getting an non existing path returns nothing" $ do
+      c <- emptyConfig
+           & addSource (mkJsonSource' [aesonQQ| {"postgres": {"url": "some url", "ssl": true}} |])
+      res <- getKey "some.path" c
+      res `shouldBe` Nothing
+
+    describe "with an array" $ do
+      it "getting a path with number gets the right value" $ do
+        c <- emptyConfig
+             & addSource (mkJsonSource'
+                          [aesonQQ| {"key": ["value"]} |])
+        res <- getKey "key.0" c
+        res `shouldBe` Just "value"
+
+    describe "with an object" $ do
+      it "getting an existing path returns nothing" $ do
+        c <- emptyConfig
+           & addSource (mkJsonSource'
+            [aesonQQ| {"key": { "path": "value"}} |])
+        res <- getKey "key" c
+        res `shouldBe` Nothing
+
+    describe "with an int" $ do
+      it "getting an existing path returns the right value" $ do
+        c <- emptyConfig
+           & addSource (mkJsonSource' [aesonQQ| {"key": 1} |])
+        res <- getKey "key" c
+        res `shouldBe` Just "1"
+
+    describe "with a float" $ do
+      it "getting an existing path returns the right value" $ do
+        c <- emptyConfig
+           & addSource (mkJsonSource' [aesonQQ| {"key": 1.2} |])
+        res <- getKey "key" c
+        res `shouldBe` Just "1.2"
+
+    describe "with a boolean" $ do
+      it "getting an existing path returns the right value" $ do
+        c <- emptyConfig
+           & addSource (mkJsonSource' [aesonQQ| {"key": false} |])
+        res <- getKey "key" c
+        res `shouldBe` Just "false"
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,1 @@
+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
