diff --git a/main/JSON2SBP.hs b/main/JSON2SBP.hs
new file mode 100644
--- /dev/null
+++ b/main/JSON2SBP.hs
@@ -0,0 +1,40 @@
+-- |
+-- Module:      JSON2SBP
+-- Copyright:   Copyright (C) 2015 Swift Navigation, Inc.
+-- License:     LGPL-3
+-- Maintainer:  Mark Fine <dev@swiftnav.com>
+-- Stability:   experimental
+-- Portability: portable
+--
+-- JSON to SBP tool - reads SBP JSON from stdin and sends SBP JSON to
+-- stdout.
+
+import           BasicPrelude
+import           Control.Monad.Trans.Resource
+import           Data.Aeson
+import           Data.Conduit
+import           Data.Conduit.Binary
+import qualified Data.Conduit.List as CL
+import           Data.Conduit.Serialization.Binary
+import qualified Data.Conduit.Text as CT
+import           SwiftNav.SBP
+import           System.IO
+
+newtype SBPMsgData = SBPMsgData
+  { sbpMsgData :: SBPMsg
+  } deriving ( Show, Read, Eq )
+
+instance FromJSON SBPMsgData where
+  parseJSON (Object v) = SBPMsgData <$> v .: "data"
+  parseJSON _ = mzero
+
+-- | Decode a SBPMsg from JSON.
+decodeSBPMsg :: ByteString -> Maybe SBPMsg
+decodeSBPMsg v = decodeStrict v <|> (fmap sbpMsgData $ decodeStrict v)
+
+main :: IO ()
+main = runResourceT $
+  sourceHandle stdin =$=
+  CT.decode CT.utf8 =$= CT.lines =$= CL.mapMaybe (decodeSBPMsg . encodeUtf8) =$=
+  conduitEncode $$
+  sinkHandle stdout
diff --git a/main/SBP2JSON.hs b/main/SBP2JSON.hs
new file mode 100644
--- /dev/null
+++ b/main/SBP2JSON.hs
@@ -0,0 +1,35 @@
+-- |
+-- Module:      SBP2JSON
+-- Copyright:   Copyright (C) 2015 Swift Navigation, Inc.
+-- License:     LGPL-3
+-- Maintainer:  Mark Fine <dev@swiftnav.com>
+-- Stability:   experimental
+-- Portability: portable
+--
+-- SBP to JSON tool - reads SBP binary from stdin and sends SBP JSON
+-- to stdout.
+
+import           BasicPrelude
+import           Control.Monad.Trans.Resource
+import           Data.Aeson
+import           Data.Aeson.Encode
+import           Data.ByteString.Builder
+import qualified Data.ByteString.Lazy as BL
+import           Data.Conduit
+import           Data.Conduit.Binary
+import qualified Data.Conduit.List as CL
+import           Data.Conduit.Serialization.Binary
+import           SwiftNav.SBP
+import           System.IO
+
+-- | Encode a SBPMsg to a line of JSON.
+encodeLine :: SBPMsg -> ByteString
+encodeLine v = BL.toStrict $ toLazyByteString $
+  encodeToByteStringBuilder (toJSON v) <> "\n"
+
+main :: IO ()
+main = runResourceT $
+  sourceHandle stdin =$=
+  conduitDecode =$=
+  CL.map encodeLine $$
+  sinkHandle stdout
diff --git a/sbp.cabal b/sbp.cabal
--- a/sbp.cabal
+++ b/sbp.cabal
@@ -1,5 +1,5 @@
 name:                  sbp
-version:               0.51.1
+version:               0.51.2
 synopsis:              SwiftNav's SBP Library
 homepage:              https://github.com/swift-nav/libsbp
 license:               LGPL-3
@@ -61,6 +61,41 @@
                        NoImplicitPrelude
                        OverloadedStrings
 
+executable sbp2json
+  hs-source-dirs:      main
+  main-is:             SBP2JSON.hs
+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N -Wall
+  build-depends:       aeson
+                     , base
+                     , basic-prelude
+                     , binary-conduit
+                     , bytestring
+                     , conduit
+                     , conduit-combinators
+                     , conduit-extra
+                     , resourcet
+                     , sbp
+  default-language:    Haskell2010
+  default-extensions:  NoImplicitPrelude
+                       OverloadedStrings
+
+executable json2sbp
+  hs-source-dirs:      main
+  main-is:             JSON2SBP.hs
+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N -Wall
+  build-depends:       aeson
+                     , base
+                     , basic-prelude
+                     , binary-conduit
+                     , bytestring
+                     , conduit
+                     , conduit-combinators
+                     , conduit-extra
+                     , resourcet
+                     , sbp
+  default-language:    Haskell2010
+  default-extensions:  NoImplicitPrelude
+                       OverloadedStrings
 benchmark bench
   type:                exitcode-stdio-1.0
   hs-source-dirs:      bench
