diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,9 @@
 # Revision history for haskell-lsp-types
 
+## 0.15.0.0 -- 2019-07-01
+
+* Normalize URIs to avoid issues with percent encoding (@cocreature)
+
 ## 0.14.0.1 -- 2019-06-13
 
 * Fix Haddock error
diff --git a/haskell-lsp-types.cabal b/haskell-lsp-types.cabal
--- a/haskell-lsp-types.cabal
+++ b/haskell-lsp-types.cabal
@@ -1,5 +1,5 @@
 name:                haskell-lsp-types
-version:             0.14.0.1
+version:             0.15.0.0
 synopsis:            Haskell library for the Microsoft Language Server Protocol, data types
 
 description:         An implementation of the types to allow language implementors to
diff --git a/src/Language/Haskell/LSP/Types/Message.hs b/src/Language/Haskell/LSP/Types/Message.hs
--- a/src/Language/Haskell/LSP/Types/Message.hs
+++ b/src/Language/Haskell/LSP/Types/Message.hs
@@ -382,7 +382,16 @@
     , _error   :: Maybe ResponseError
     } deriving (Read,Show,Eq)
 
-deriveJSON lspOptions ''ResponseMessage
+deriveToJSON lspOptions ''ResponseMessage
+
+instance FromJSON a => FromJSON (ResponseMessage a) where
+  parseJSON = withObject "Response" $ \o ->
+    ResponseMessage
+      <$> o .: "jsonrpc"
+      <*> o .: "id"
+      -- It is important to use .:! so that result = null gets decoded as Just Nothing
+      <*> o .:! "result"
+      <*> o .:! "error"
 
 type ErrorResponse = ResponseMessage ()
 
diff --git a/src/Language/Haskell/LSP/Types/Uri.hs b/src/Language/Haskell/LSP/Types/Uri.hs
--- a/src/Language/Haskell/LSP/Types/Uri.hs
+++ b/src/Language/Haskell/LSP/Types/Uri.hs
@@ -19,6 +19,19 @@
 
 instance NFData Uri
 
+-- | When URIs are supposed to be used as keys, it is important to normalize
+-- the percent encoding in the URI since URIs that only differ
+-- when it comes to the percent-encoding should be treated as equivalent.
+newtype NormalizedUri = NormalizedUri Text
+  deriving (Eq,Ord,Read,Show,Generic,Hashable)
+
+toNormalizedUri :: Uri -> NormalizedUri
+toNormalizedUri (Uri t) =
+    NormalizedUri $ T.pack $ escapeURIString isUnescapedInURI $ unEscapeString $ T.unpack t
+
+fromNormalizedUri :: NormalizedUri -> Uri
+fromNormalizedUri (NormalizedUri t) = Uri t
+
 fileScheme :: String
 fileScheme = "file:"
 
