diff --git a/Data/JsonStream/Conduit.hs b/Data/JsonStream/Conduit.hs
new file mode 100644
--- /dev/null
+++ b/Data/JsonStream/Conduit.hs
@@ -0,0 +1,25 @@
+-- |
+-- Module : Data.JsonStream.Conduit
+-- License     : BSD-style
+--
+-- Stability   : experimental
+-- Portability : portable
+--
+-- Use "Data.JsonStream.Parser" parsers in "Data.Conduit".
+
+module Data.JsonStream.Conduit (
+  parserConduit
+) where
+
+import           Data.ByteString (ByteString)
+import qualified Data.Conduit.Internal as C
+
+import           Data.JsonStream.Parser
+
+-- |Use a 'Parser' as a conduit from 'ByteString' input chunks to results, finally returning any parse error or 'Nothing' on success.
+parserConduit :: Parser a -> C.ConduitT ByteString a m (Maybe String)
+parserConduit ps = C.ConduitT (parsePipe $ runParser ps) where
+  parsePipe (ParseYield a p) r = C.HaveOutput (parsePipe p r) a
+  parsePipe (ParseNeedData f) r = C.NeedInput (\i -> parsePipe (f i) r) (\() -> r (Just "Incomplete JSON"))
+  parsePipe (ParseFailed e) r = r (Just e)
+  parsePipe (ParseDone l) r = C.Leftover (r Nothing) l
diff --git a/Data/JsonStream/Parser.hs b/Data/JsonStream/Parser.hs
--- a/Data/JsonStream/Parser.hs
+++ b/Data/JsonStream/Parser.hs
@@ -47,6 +47,7 @@
   , eitherDecodeStrict
     -- * FromJSON parser
   , value
+  , valueWith
   , string
   , byteString
     -- * Constant space parsers
@@ -74,6 +75,7 @@
   , filterI
   , takeI
   , mapWithFailure
+  , manyReverse
     -- * SAX-like parsers
   , arrayFound
   , objectFound
@@ -89,6 +91,7 @@
 
 import           Control.Applicative
 import qualified Data.Aeson                  as AE
+import qualified Data.Aeson.Types            as AE
 import qualified Data.ByteString.Char8       as BS
 import qualified Data.ByteString.Lazy.Char8  as BL
 import qualified Data.ByteString.Lazy.Internal as BL
@@ -398,7 +401,9 @@
         ObjectBegin -> AE.Object . tomap <$> callParse (manyReverse (objectItems aeValue)) tok
         _ -> Failed ("aeValue - unexpected token: " ++ show el)
 
--- | Optimized function for aeson objects - evades reversing the objects
+-- | Identical to @fmap 'reverse' . 'many'@ but more efficient.
+-- If you don't care about the order of the results but plan to fully evaluate the list,
+-- this can be slightly more efficient than 'many' as it avoids the accumulating thunks.
 manyReverse :: Parser a -> Parser [a]
 manyReverse f = Parser $ \ntok -> loop [] (callParse f ntok)
   where
@@ -544,21 +549,25 @@
     value' _ (JValue AE.Null) ntok = Yield Nothing (Done "" ntok)
     value' tok _ _ = callParse (Just <$> valparse) tok
 
--- | Match 'FromJSON' value. Calls parseJSON on the parsed value.
---
--- >>> let json = "[{\"key1\": [1,2], \"key2\": [5,6]}]"
--- >>> parseByteString (arrayOf value) json :: [AE.Value]
--- [Object (fromList [("key2",Array [Number 5.0,Number 6.0]),("key1",Array [Number 1.0,Number 2.0])])]
-value :: AE.FromJSON a => Parser a
-value = Parser $ \ntok -> loop (callParse aeValue ntok)
+-- | Match values with a 'AE.Parser'.  Returns values for which the given parser succeeds.
+valueWith :: (AE.Value -> AE.Parser a) -> Parser a
+valueWith jparser = Parser $ \ntok -> loop (callParse aeValue ntok)
   where
     loop (Done ctx ntp) = Done ctx ntp
     loop (Failed err) = Failed err
     loop (MoreData (Parser np, ntok)) = MoreData (Parser (loop . np), ntok)
     loop (Yield v np) =
-      case AE.fromJSON v of
+      case AE.parse jparser v of
         AE.Error _ -> loop np
         AE.Success res -> Yield res (loop np)
+
+-- | Match 'AE.FromJSON' value. Equivalent to @'valueWith' 'AE.parseJSON'@.
+--
+-- >>> let json = "[{\"key1\": [1,2], \"key2\": [5,6]}]"
+-- >>> parseByteString (arrayOf value) json :: [AE.Value]
+-- [Object (fromList [("key2",Array [Number 5.0,Number 6.0]),("key1",Array [Number 1.0,Number 2.0])])]
+value :: AE.FromJSON a => Parser a
+value = valueWith AE.parseJSON
 
 -- | Take maximum n matching items.
 --
diff --git a/Data/JsonStream/Unescape.hs b/Data/JsonStream/Unescape.hs
--- a/Data/JsonStream/Unescape.hs
+++ b/Data/JsonStream/Unescape.hs
@@ -1,28 +1,48 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE ForeignFunctionInterface #-}
 {-# LANGUAGE MagicHash                #-}
 {-# LANGUAGE UnliftedFFITypes         #-}
+{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE MultiWayIf   #-}
 
 module Data.JsonStream.Unescape (
   unescapeText
 ) where
 
-import           Control.Exception          (evaluate, throw, try)
-import           Control.Monad.ST.Unsafe    (unsafeIOToST, unsafeSTToIO)
 import           Data.ByteString            as B
 import           Data.ByteString.Internal   as B hiding (c2w)
-import qualified Data.Text.Array            as A
 import           Data.Text.Encoding.Error   (UnicodeException (..))
 import           Data.Text.Internal         (Text (..))
-import           Data.Text.Internal.Private (runText)
 import           Data.Text.Unsafe           (unsafeDupablePerformIO)
-import           Data.Word                  (Word8)
-import           Foreign.C.Types            (CInt (..), CSize (..))
+import           Data.Word                  (Word8, Word32)
 import           Foreign.ForeignPtr         (withForeignPtr)
-import           Foreign.Marshal.Utils      (with)
 import           Foreign.Ptr                (Ptr, plusPtr)
 import           Foreign.Storable           (peek)
+
+#if MIN_VERSION_text(2,0,0)
+
+import qualified Data.Primitive           as P
+import qualified Data.Text.Array          as T
+import qualified Data.Text.Internal       as T
+import           Data.Bits                (shiftL, shiftR, (.&.), (.|.))
+import           Control.Exception        (try, throwIO)
+import Foreign.ForeignPtr (ForeignPtr)
+import GHC.ForeignPtr (plusForeignPtr)
+
+#else
+
+import           Control.Exception          (evaluate, throw, try)
+import           Control.Monad.ST.Unsafe    (unsafeIOToST, unsafeSTToIO)
+import           Data.Text.Internal.Private (runText)
+import           Foreign.Marshal.Utils      (with)
+import qualified Data.Text.Array            as A
 import           GHC.Base                   (MutableByteArray#)
+import           Foreign.C.Types            (CInt (..), CSize (..))
 
+#endif
+
+#if !MIN_VERSION_text(2,0,0)
+
 foreign import ccall unsafe "_jstream_decode_string" c_js_decode
     :: MutableByteArray# s -> Ptr CSize
     -> Ptr Word8 -> Ptr Word8 -> IO CInt
@@ -49,3 +69,383 @@
 unescapeText :: ByteString -> Either UnicodeException Text
 unescapeText = unsafeDupablePerformIO . try . evaluate . unescapeText'
 {-# INLINE unescapeText #-}
+
+#else
+
+withBS :: ByteString -> (ForeignPtr Word8 -> Int -> r) -> r
+#if MIN_VERSION_bytestring(0,11,0)
+withBS (BS !sfp !slen)       kont = kont sfp slen
+#else
+withBS (PS !sfp !soff !slen) kont = kont (plusForeignPtr sfp soff) slen
+#endif
+{-# INLINE withBS #-}
+
+unescapeText :: ByteString -> Either UnicodeException Text
+unescapeText = unsafeDupablePerformIO . try . unescapeTextIO
+
+throwDecodeError :: IO a
+throwDecodeError =
+  let desc = "Data.Text.Internal.Encoding.decodeUtf8: Invalid UTF-8 stream"
+   in throwIO (DecodeError desc Nothing)
+
+-- The following is copied from aeson-2.0 
+
+-------------------------------------------------------------------------------
+-- unescapeTextIO
+-------------------------------------------------------------------------------
+
+-- This function is generated using staged-streams
+-- See: https://github.com/phadej/staged/blob/master/staged-streams-unicode/src/Unicode/JSON.hs
+--
+-- Because @aeson@ better to not use template-haskell itself,
+-- we dump the splice and prettify it by hand a bit.
+--
+unescapeTextIO :: ByteString -> IO Text
+unescapeTextIO bs = withBS bs $ \fptr len ->
+  withForeignPtr fptr $ \begin -> do
+    let end :: Ptr Word8
+        end = plusPtr begin len
+
+    arr <- P.newPrimArray len
+
+    let write3bytes :: Int -> Word8 -> Word8 -> Word8 -> Ptr Word8 -> IO Text
+        write3bytes !out !b1 !b2 !b3 !inp = do
+          P.writePrimArray arr out b1
+          write2bytes (out + 1) b2 b3 inp
+
+        write2bytes :: Int -> Word8 -> Word8 -> Ptr Word8 -> IO Text
+        write2bytes !out !b1 !b2 !inp = do
+          P.writePrimArray arr out b1
+          write1byte (out + 1) b2 inp
+
+        write1byte :: Int -> Word8 -> Ptr Word8 -> IO Text
+        write1byte !out !b1 !inp = do
+          P.writePrimArray arr out b1
+          state_start (out + 1) inp
+
+        writeCodePoint :: Int -> Ptr Word8 -> Word32 -> IO Text
+        writeCodePoint !out !inp !acc
+          | acc <= 127 = do
+            P.writePrimArray arr out (fromIntegral acc :: Word8)
+            state_start (out + 1) (plusPtr inp 1)
+
+          | acc <= 2047 = do
+            let b1 = fromIntegral (shiftR acc 6 .|. 192) :: Word8
+            let b2 = fromIntegral ((acc .&. 63) .|. 128) :: Word8
+            P.writePrimArray arr out b1
+            write1byte (out + 1) b2 (plusPtr inp 1)
+
+          | acc <= 65535 = do
+            let b1 = fromIntegral (shiftR acc 12 .|. 224) :: Word8
+            let b2 = fromIntegral ((shiftR acc 6 .&. 63) .|.  128) :: Word8
+            let b3 = fromIntegral ((acc .&. 63) .|. 128) :: Word8
+            P.writePrimArray arr out b1
+            write2bytes (out + 1) b2 b3 (plusPtr inp 1)
+
+          | otherwise = do
+            let b1 = fromIntegral (shiftR acc 18 .|. 240) :: Word8
+            let b2 = fromIntegral ((shiftR acc 12 .&. 63) .|. 128) :: Word8
+            let b3 = fromIntegral ((shiftR acc 6 .&. 63) .|. 128) :: Word8
+            let b4 = fromIntegral ((acc .&. 63) .|. 128) :: Word8
+            P.writePrimArray arr out b1
+            write3bytes (out + 1) b2 b3 b4 (plusPtr inp 1)
+
+        state_sudone :: Int -> Ptr Word8 -> Word32 -> Word32 -> IO Text
+        state_sudone !out !inp !hi !lo
+          | 56320 <= lo, lo <= 57343
+          = writeCodePoint out inp (65536 + (shiftL (hi - 55296) 10 .|.  (lo - 56320)))
+          
+          | otherwise
+          = throwDecodeError
+
+        state_su4 :: Int -> Ptr Word8 -> Word32 -> Word32 -> IO Text
+        state_su4 !out !inp !hi !acc
+          | inp == end = throwDecodeError
+          | otherwise = do
+            w8 <- peek inp
+            if | 48 <= w8, w8 <= 57 ->
+                 state_sudone out inp hi (shiftL acc 4 .|. fromIntegral (w8 - 48))
+               | 65 <= w8, w8 <= 70 ->
+                 state_sudone out inp hi (shiftL acc 4 .|. fromIntegral (w8 - 55))
+               | 97 <= w8, w8 <= 102 ->
+                 state_sudone out inp hi (shiftL acc 4 .|. fromIntegral (w8 - 87))
+               | otherwise ->
+                 throwDecodeError
+
+        state_su3 :: Int -> Ptr Word8 -> Word32 -> Word32 -> IO Text
+        state_su3 !out !inp !hi !acc
+          | inp == end = throwDecodeError
+          | otherwise = do
+            w8 <- peek inp
+            if | 48 <= w8, w8 <= 57 ->
+                 state_su4 out (plusPtr inp 1) hi (shiftL acc 4 .|. fromIntegral (w8 - 48))
+               | 65 <= w8, w8 <= 70 ->
+                 state_su4 out (plusPtr inp 1) hi (shiftL acc 4 .|. fromIntegral (w8 - 55))
+               | 97 <= w8, w8 <= 102 ->
+                 state_su4 out (plusPtr inp 1) hi (shiftL acc 4 .|. fromIntegral (w8 - 87))
+               | otherwise ->
+                 throwDecodeError
+
+        state_su2 :: Int -> Ptr Word8 -> Word32 -> Word32 -> IO Text
+        state_su2 !out !inp !hi !acc
+          | inp == end = throwDecodeError
+          | otherwise = do
+            w8 <- peek inp
+            if | 48 <= w8, w8 <= 57 -> 
+                 state_su3 out (plusPtr inp 1) hi (shiftL acc 4 .|. fromIntegral (w8 - 48))
+               | 65 <= w8, w8 <= 70 ->
+                 state_su3 out (plusPtr inp 1) hi (shiftL acc 4 .|. fromIntegral (w8 - 55))
+               | 97 <= w8, w8 <= 102 ->
+                 state_su3 out (plusPtr inp 1) hi (shiftL acc 4 .|. fromIntegral (w8 - 87))
+               | otherwise ->
+                 throwDecodeError
+
+        state_su1 :: Int -> Ptr Word8 -> Word32 -> IO Text
+        state_su1 !out !inp !hi
+          | inp == end = throwDecodeError
+          | otherwise = do
+            w8 <- peek inp
+            if | 48 <= w8, w8 <= 57 ->
+                 state_su2 out (plusPtr inp 1) hi (fromIntegral (w8 - 48))
+               | 65 <= w8, w8 <= 70 ->
+                 state_su2 out (plusPtr inp 1) hi (fromIntegral (w8 - 55))
+               | 97 <= w8, w8 <= 102 ->
+                 state_su2 out (plusPtr inp 1) hi (fromIntegral (w8 - 87))
+               | otherwise ->
+                 throwDecodeError
+
+        state_su :: Int -> Ptr Word8 -> Word32 -> IO Text
+        state_su !out !inp !hi
+          | inp == end = throwDecodeError
+          | otherwise = do
+            w8 <- peek inp
+            case w8 of
+              117 -> state_su1 out (plusPtr inp 1) hi
+              _   -> throwDecodeError
+
+        state_ss :: Int -> Ptr Word8 -> Word32 -> IO Text
+        state_ss !out !inp !hi
+          | inp == end = throwDecodeError
+          | otherwise = do
+            w8 <- peek inp
+            case w8 of
+              92 -> state_su out (plusPtr inp 1) hi
+              _  -> throwDecodeError
+
+        state_udone :: Int -> Ptr Word8 -> Word32 -> IO Text
+        state_udone !out !inp !acc
+          | acc < 55296 || acc > 57343 =
+            writeCodePoint out inp acc
+
+          | acc < 56320 =
+            state_ss out (plusPtr inp 1) acc
+
+          | otherwise =
+            throwDecodeError
+
+        state_u4 :: Int -> Ptr Word8 -> Word32 -> IO Text
+        state_u4 !out !inp !acc
+          | inp == end = throwDecodeError
+          | otherwise = do
+            w8 <- peek inp
+            if | 48 <= w8, w8 <= 57 ->
+                 state_udone out inp (shiftL acc 4 .|. fromIntegral (w8 - 48))
+               | 65 <= w8, w8 <= 70 ->
+                 state_udone out inp (shiftL acc 4 .|. fromIntegral (w8 - 55))
+               | 97 <= w8, w8 <= 102 ->
+                 state_udone out inp (shiftL acc 4 .|. fromIntegral (w8 - 87))
+               | otherwise ->
+                 throwDecodeError
+
+        state_u3 :: Int -> Ptr Word8 -> Word32 -> IO Text
+        state_u3 !out !inp !acc
+          | inp == end = throwDecodeError
+          | otherwise = do
+            w8 <- peek inp
+            if | 48 <= w8, w8 <= 57 ->
+                 state_u4 out (plusPtr inp 1) (shiftL acc 4 .|. fromIntegral (w8 - 48))
+               | 65 <= w8, w8 <= 70 ->
+                 state_u4 out (plusPtr inp 1) (shiftL acc 4 .|. fromIntegral (w8 - 55))
+               | 97 <= w8, w8 <= 102 ->
+                 state_u4 out (plusPtr inp 1) (shiftL acc 4 .|. fromIntegral (w8 - 87))
+               | otherwise ->
+                 throwDecodeError
+
+        state_u2 :: Int -> Ptr Word8 -> Word32 -> IO Text
+        state_u2 !out !inp !acc
+          | inp == end = throwDecodeError
+          | otherwise = do
+            w8 <- peek inp
+            if | 48 <= w8, w8 <= 57 ->
+                 state_u3 out (plusPtr inp 1) (shiftL acc 4 .|. fromIntegral (w8 - 48))
+               | 65 <= w8, w8 <= 70 ->
+                 state_u3 out (plusPtr inp 1) (shiftL acc 4 .|. fromIntegral (w8 - 55))
+               | 97 <= w8, w8 <= 102 ->
+                 state_u3 out (plusPtr inp 1) (shiftL acc 4 .|. fromIntegral (w8 - 87))
+               | otherwise ->
+                 throwDecodeError
+
+        state_u1 :: Int -> Ptr Word8 -> IO Text
+        state_u1 !out !inp
+          | inp == end = throwDecodeError
+          | otherwise = do
+            w8 <- peek inp
+            if | 48 <= w8, w8 <= 57 ->
+                 state_u2 out (plusPtr inp 1) (fromIntegral (w8 - 48))
+               | 65 <= w8, w8 <= 70 ->
+                 state_u2 out (plusPtr inp 1) (fromIntegral (w8 - 55))
+               | 97 <= w8, w8 <= 102 ->
+                 state_u2 out (plusPtr inp 1) (fromIntegral (w8 - 87))
+               | otherwise ->
+                 throwDecodeError
+
+        state_escape :: Int -> Ptr Word8 -> IO Text
+        state_escape !out !inp
+          | inp == end = throwDecodeError
+          | otherwise  = do
+            w8 <- peek inp
+            case w8 of
+              34 -> do
+                P.writePrimArray arr out 34
+                state_start (out + 1) (plusPtr inp 1)
+
+              92 -> do
+                P.writePrimArray arr out 92
+                state_start (out + 1) (plusPtr inp 1)
+
+              47 -> do
+                P.writePrimArray arr out 47
+                state_start (out + 1) (plusPtr inp 1)
+
+              98 -> do
+                P.writePrimArray arr out 8
+                state_start (out + 1) (plusPtr inp 1)
+
+              102 -> do
+                P.writePrimArray arr out 12
+                state_start (out + 1) (plusPtr inp 1)
+
+              110 -> do
+                P.writePrimArray arr out 10
+                state_start (out + 1) (plusPtr inp 1)
+
+              114 -> do
+                P.writePrimArray arr out 13
+                state_start (out + 1) (plusPtr inp 1)
+
+              116 -> do
+                P.writePrimArray arr out 9
+                state_start (out + 1) (plusPtr inp 1)
+
+              117 ->
+                state_u1 out (plusPtr inp 1)
+
+              _ -> throwDecodeError
+
+        state_input4c :: Int -> Ptr Word8 -> Word8 -> Word8 -> Word8 -> IO Text
+        state_input4c !out !inp !b1 !b2 !b3
+          | inp == end = throwDecodeError
+          | otherwise  = do
+            w8 <- peek inp
+            if | (w8 .&. 192) == 128
+               , let acc    = shiftL (fromIntegral (b1 .&. 7)) 18
+               , let acc'   = acc .|. shiftL (fromIntegral (b2 .&. 63)) 12
+               , let acc''  = acc' .|. shiftL (fromIntegral (b3 .&. 63)) 6
+               , let acc''' = acc'' .|. fromIntegral (w8 .&. 63) :: Word32
+               , acc''' >= 65536 && acc''' < 1114112 -> do
+                 P.writePrimArray arr out b1
+                 write3bytes (out + 1) b2 b3 w8 (plusPtr inp 1)
+
+               | otherwise ->
+                 throwDecodeError
+
+        state_input4b :: Int -> Ptr Word8 -> Word8 -> Word8 -> IO Text
+        state_input4b !out !inp !b1 !b2
+          | inp == end = throwDecodeError
+          | otherwise  = do
+            w8 <- peek inp
+            if | (w8 .&. 192) == 128 ->
+                 state_input4c out (plusPtr inp 1) b1 b2 w8
+
+               | otherwise ->
+                 throwDecodeError
+
+        state_input4 :: Int -> Ptr Word8 -> Word8 -> IO Text
+        state_input4 !out !inp !b1
+          | inp == end = throwDecodeError
+          | otherwise  = do
+            w8 <- peek inp
+            if | (w8 .&. 192) == 128 ->
+                 state_input4b out (plusPtr inp 1) b1 w8
+
+               | otherwise ->
+                 throwDecodeError
+
+        state_input3b :: Int -> Ptr Word8 -> Word8 -> Word8 -> IO Text
+        state_input3b !out !inp !b1 !b2
+          | inp == end = throwDecodeError
+          | otherwise  = do
+            w8 <- peek inp
+            if | (w8 .&. 192) == 128
+               , let acc   = shiftL (fromIntegral (b1 .&. 15)) 12
+               , let acc'  = acc .|.  shiftL (fromIntegral (b2 .&. 63)) 6
+               , let acc'' = acc' .|. fromIntegral (w8 .&. 63) :: Word32
+               , (acc'' >= 2048 && acc'' < 55296) || acc'' > 57343 -> do
+                 P.writePrimArray arr out b1
+                 write2bytes (out + 1) b2 w8 (plusPtr inp 1)
+
+               | otherwise ->
+                 throwDecodeError
+
+        state_input3 :: Int -> Ptr Word8 -> Word8 -> IO Text
+        state_input3 !out !inp !b1
+          | inp == end = throwDecodeError
+          | otherwise  = do
+            w8 <- peek inp
+            if | (w8 .&. 192) == 128 ->
+                 state_input3b out (plusPtr inp 1) b1 w8
+
+               | otherwise ->
+                 throwDecodeError
+
+        state_input2 :: Int -> Ptr Word8 -> Word8 -> IO Text
+        state_input2 !out !inp !b1
+          | inp == end = throwDecodeError
+          | otherwise  = do
+            w8 <- peek inp
+            if | (w8 .&. 192) == 128,
+                 let acc = shiftL (fromIntegral (b1 .&. 63)) 6 :: Word32
+                     acc' = acc .|. fromIntegral (w8 .&. 63) :: Word32
+               , acc' >= 128 -> do
+                 P.writePrimArray arr out b1
+                 write1byte (out + 1) w8 (plusPtr inp 1)
+
+               | otherwise ->
+                 throwDecodeError
+
+        state_start :: Int -> Ptr Word8 -> IO Text
+        state_start !out !inp
+          | inp == end = do
+            P.shrinkMutablePrimArray arr out
+            frozenArr <- P.unsafeFreezePrimArray arr
+            return $ case frozenArr of
+              P.PrimArray ba -> T.Text (T.ByteArray ba) 0 out
+
+          | otherwise = do
+            w8 <- peek inp
+            if | w8 == 92 -> state_escape out (plusPtr inp 1)
+               | w8 < 128 -> do
+                 P.writePrimArray arr out w8
+                 state_start (out + 1) (plusPtr inp 1)
+
+               | w8 < 192 -> throwDecodeError
+               | w8 < 224 -> state_input2 out (plusPtr inp 1) w8
+               | w8 < 240 -> state_input3 out (plusPtr inp 1) w8
+               | w8 < 248 -> state_input4 out (plusPtr inp 1) w8
+
+               | otherwise -> throwDecodeError
+
+    -- start the state machine
+    state_start (0 :: Int) begin
+
+#endif
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # json-stream - Applicative incremental JSON parser for Haskell
 
-[![Build Status](https://travis-ci.org/ondrap/json-stream.svg?branch=master)](https://travis-ci.org/ondrap/json-stream) [![Hackage](https://img.shields.io/hackage/v/json-stream.svg)](https://hackage.haskell.org/package/json-stream)
+[![Hackage](https://img.shields.io/hackage/v/json-stream.svg)](https://hackage.haskell.org/package/json-stream)
 
 # When to use this library
 
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,10 @@
+# 0.4.4.0
+
+- added text 2.0 compatibility
+- added conduit interface behind a flag (Dylan Simon)
+- added manyReverse (Dylan Simon)
+- added valueWith (Dylan Simon)
+
 # 0.4.3.0
 
 - Aeson 2.0 compatibility
diff --git a/json-stream.cabal b/json-stream.cabal
--- a/json-stream.cabal
+++ b/json-stream.cabal
@@ -1,5 +1,5 @@
 name:                json-stream
-version:             0.4.3.0
+version:             0.4.4.0
 synopsis:            Incremental applicative JSON parser
 description:         Easy to use JSON parser fully supporting incremental parsing.
                      Parsing grammar in applicative form.
@@ -28,6 +28,10 @@
   type: git
   location: https://github.com/ondrap/json-stream.git
 
+flag conduit
+  description: Support the conduit package
+  manual: True
+  default: False
 
 library
   exposed-modules:     Data.JsonStream.Parser
@@ -45,6 +49,10 @@
                        , vector
                        , unordered-containers
                        , scientific
+                       , primitive
+  if flag(conduit)
+    exposed-modules:     Data.JsonStream.Conduit
+    build-depends:       conduit
 
   default-language:    Haskell2010
   Ghc-Options:         -Wall -fwarn-incomplete-uni-patterns
@@ -104,6 +112,8 @@
                        , directory
                        , QuickCheck
                        , quickcheck-unicode
+                       , primitive
+
 
 -- executable spdtest
 --   main-is: spdtest.hs
diff --git a/test/ParserSpec.hs b/test/ParserSpec.hs
--- a/test/ParserSpec.hs
+++ b/test/ParserSpec.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE CPP                 #-}
 module ParserSpec where
 
 import Control.Applicative
@@ -12,10 +13,14 @@
 import Control.Monad (forM_)
 import Data.Text.Encoding (encodeUtf8)
 import qualified Data.Vector as Vec
-import qualified Data.HashMap.Strict as HMap
 import System.Directory (getDirectoryContents)
 import Data.Int
 import Data.Word
+#if MIN_VERSION_aeson(2,0,0)
+import qualified Data.Aeson.KeyMap           as AEK
+#else
+import qualified Data.HashMap.Strict as HMap
+#endif
 
 import Data.JsonStream.Parser
 
@@ -124,13 +129,19 @@
         msg = parseLazyByteString parser (BL.fromChunks test) :: [BS.ByteString]
     msg `shouldBe` ["abcd\\n\\rxyz"]
 
+
+
 specEdge :: Spec
 specEdge = describe "Edge cases" $ do
   it "Correct incremental parsing 1" $ do
     let msg1 = "[ {\"test1\"  :[1,true,false,null,-3.591e+1,[12,13]], \"test2\":\"123\\r\\n\\\"\\u0041\"}]"
         pmsg = BL.fromChunks $ map BS.singleton msg1
         res = parseLazyByteString value pmsg :: [AE.Value]
+#if MIN_VERSION_aeson(2,0,0)
+    res `shouldBe` [Array (Vec.fromList [Object $ AEK.fromList [("test2",String "123\r\n\"A"),("test1",Array (Vec.fromList [Number 1.0,Bool True,Bool False,Null,Number (-35.91),Array (Vec.fromList [Number 12.0,Number 13.0])]))]])]
+#else
     res `shouldBe` [Array (Vec.fromList [Object $ HMap.fromList [("test2",String "123\r\n\"A"),("test1",Array (Vec.fromList [Number 1.0,Bool True,Bool False,Null,Number (-35.91),Array (Vec.fromList [Number 12.0,Number 13.0])]))]])]
+#endif
 
   it "Correct incremental parsing 2" $ do
     let msg1 = "{\"test1\"  :[1,true,false,null,-3.591e+1,[12,13]], \"test2\":\"test2string\"}"
