diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Li Meng Jun (c) 2017
+
+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 Li Meng Jun 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.
diff --git a/aeson-result.cabal b/aeson-result.cabal
new file mode 100644
--- /dev/null
+++ b/aeson-result.cabal
@@ -0,0 +1,27 @@
+name:                aeson-result
+version:             0.1.0.0
+synopsis:            API Result for aeson
+description:         API Result for aeson. Make json rest ful api stand.
+homepage:            https://github.com/Lupino/yuntan-common/tree/master/aeson-result#readme
+license:             BSD3
+license-file:        LICENSE
+author:              Li Meng Jun
+maintainer:          lmjubuntu@gmail.com
+copyright:           MIT
+category:            Web,Aeson,API
+build-type:          Simple
+-- extra-source-files:
+cabal-version:       >=1.10
+
+library
+  hs-source-dirs:      src
+  exposed-modules:     Data.Aeson.Result
+  build-depends:       base >= 4.7 && < 5
+                     , aeson
+                     , text
+                     , aeson-helper
+  default-language:    Haskell2010
+
+source-repository head
+  type:     git
+  location: https://github.com/Lupino/yuntan-common
diff --git a/src/Data/Aeson/Result.hs b/src/Data/Aeson/Result.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aeson/Result.hs
@@ -0,0 +1,143 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards   #-}
+
+module Data.Aeson.Result
+  ( Ok (..)
+  , Err (..)
+  , err
+  , ok
+  , fromOk
+  , toOk
+  , throwError
+
+  , From
+  , Size
+  , Total
+  , List (..)
+  , emptyList
+  , merge
+
+  , toList
+  , fromList
+  ) where
+
+import           Control.Exception (Exception, throwIO)
+import           Data.Aeson        (FromJSON (..), Result (..), ToJSON (..),
+                                    Value, fromJSON, object, withObject, (.:),
+                                    (.=))
+import           Data.Aeson.Helper (replace)
+import           Data.Int          (Int64)
+import           Data.Text         (Text)
+
+type From  = Int64
+type Size  = Int64
+type Total = Int64
+
+-- | Make ok result look like    '{"data": "data value"}'
+newtype Ok a = Ok { getValue :: a }
+  deriving (Show)
+
+instance (FromJSON a) => FromJSON (Ok a) where
+  parseJSON = withObject "Ok" $ \o -> do
+    getValue <- o .: "result"
+    return Ok{..}
+
+instance (ToJSON a) => ToJSON (Ok a) where
+  toJSON Ok{..} = object [ "result" .= getValue ]
+
+-- | Make error result look like    '{"err": "error message"}'
+newtype Err = Err { errMsg :: String }
+  deriving (Show, Eq, Ord)
+
+instance Exception Err
+
+-- | Throw error to IO
+throwError :: Err -> IO a
+throwError = throwIO
+
+instance FromJSON Err where
+  parseJSON = withObject "Err" $ \o -> do
+    errMsg <- o .: "err"
+    return Err{..}
+
+instance ToJSON Err where
+  toJSON Err{..} = object [ "err" .= errMsg ]
+
+-- | Initial Err
+err :: String -> Err
+err = Err
+
+
+-- | Initial Ok
+ok :: a -> Ok a
+ok = Ok
+
+-- | Make a JSON result to Ok
+toOk :: FromJSON a => Text -> Value -> Maybe (Ok a)
+toOk okey v =
+  case fromJSON (replace okey "result" v) of
+    Success v' -> Just v'
+    _          -> Nothing
+
+-- | Make an Ok to JSON
+fromOk :: ToJSON a => Text -> Ok a -> Value
+fromOk key ret = replace "result" key $ toJSON ret
+
+-- | Make list result look like '{"users": ["user1"], "total": 1, "from": 0, "size": 10}'
+data List a = List
+  { getFrom   :: From
+  , getSize   :: Size
+  , getTotal  :: Total
+  , getResult :: [a]
+  }
+  deriving (Show)
+
+
+instance FromJSON a => FromJSON (List a) where
+  parseJSON = withObject "List" $ \o -> do
+    getFrom   <- o .: "from"
+    getSize   <- o .: "size"
+    getTotal  <- o .: "total"
+    getResult <- o .: "result"
+    return List{..}
+
+instance ToJSON a => ToJSON (List a) where
+  toJSON List{..} = object
+    [ "from"   .= getFrom
+    , "size"   .= getSize
+    , "total"  .= getTotal
+    , "result" .= getResult
+    ]
+
+-- | Empty list
+emptyList :: List a
+emptyList = List
+  { getFrom = 0
+  , getSize = 10
+  , getTotal = 0
+  , getResult = []
+  }
+
+-- | Merge two list, from size and total, result is replace.
+merge :: [a] -> List b -> List a
+merge t List
+  { getFrom = from
+  , getSize = size
+  , getTotal = total
+  } = List
+  { getFrom = from
+  , getSize = size
+  , getTotal = total
+  , getResult = t
+  }
+
+-- | Make a JSON to List
+toList :: FromJSON a => Text -> Value -> Maybe (List a)
+toList okey v =
+  case fromJSON (replace okey "result" v) of
+    Success v' -> Just v'
+    _          -> Nothing
+
+-- | Make a List to JSON
+fromList :: ToJSON a => Text -> List a -> Value
+fromList key ret = replace "result" key $ toJSON ret
