diff --git a/morpheus-graphql-tests.cabal b/morpheus-graphql-tests.cabal
--- a/morpheus-graphql-tests.cabal
+++ b/morpheus-graphql-tests.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           morpheus-graphql-tests
-version:        0.27.2
+version:        0.27.3
 synopsis:       Morpheus GraphQL Test
 category:       web, graphql, test
 homepage:       https://morpheusgraphql.com
@@ -25,6 +25,7 @@
       Test.Morpheus
   other-modules:
       Test.Morpheus.File
+      Test.Morpheus.JSONDiff
       Test.Morpheus.Response
       Test.Morpheus.Utils
       Paths_morpheus_graphql_tests
diff --git a/src/Test/Morpheus/JSONDiff.hs b/src/Test/Morpheus/JSONDiff.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/Morpheus/JSONDiff.hs
@@ -0,0 +1,91 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Test.Morpheus.JSONDiff
+  ( jsonEQ,
+  )
+where
+
+import Data.Aeson (ToJSON (..), Value (..), encode)
+import Data.ByteString.Lazy.Char8 (unpack)
+import GHC.Show (Show (show))
+import Relude hiding (ByteString, Show, show)
+import Test.Tasty.HUnit (assertFailure)
+
+#if MIN_VERSION_aeson(2,0,0)
+import Data.Aeson.KeyMap (keys, lookup)
+# else
+import Data.HashMap.Lazy (keys, lookup)
+#endif
+
+data Diff
+  = DiffNode [(String, Diff)]
+  | DiffLeaf Value Value
+
+instance Show Diff where
+  show (DiffNode xs) = intercalate "\n" (map showField xs)
+    where
+      showField (k, v) = k <> ":\n  " <> indent (show v)
+  show (DiffLeaf x y) =
+    "should be:"
+      <> showLeaf x
+      <> "but it is:"
+      <> showLeaf y
+
+showLeaf :: ToJSON a => a -> [Char]
+showLeaf x = " " <> unpack (encode x) <> "\n"
+
+unescape :: String -> String
+unescape = concatMap f
+  where
+    f '\"' = ""
+    f x = x : ""
+
+indent :: String -> String
+indent = concatMap f
+  where
+    f '\n' = "\n  "
+    f x = x : ""
+
+diff :: (Value, Value) -> Maybe Diff
+diff (Object beforeFields, Object afterFields) = diffNode $ map toPair ks
+  where
+    ks = uniq (keys (beforeFields <> afterFields))
+    toPair key = (unescape (show key), (getField key beforeFields, getField key afterFields))
+    getField key = fromMaybe Null . lookup key
+diff (Array beforeElems, Array afterElems) = diffNode (zip ks vs)
+  where
+    ks = map show ([1 ..] :: [Int])
+    vs = zipOptional (toList beforeElems) (toList afterElems)
+diff (v1, v2)
+  | v1 == v2 =
+      Nothing
+  | otherwise = Just (DiffLeaf v1 v2)
+
+diffNode :: [(String, (Value, Value))] -> Maybe Diff
+diffNode values
+  | null entries = Nothing
+  | otherwise = Just (DiffNode entries)
+  where
+    entries = mapMaybe (\(key, value) -> (key,) <$> diff value) values
+
+uniq :: (Eq a) => [a] -> [a]
+uniq [] = []
+uniq (x : xs)
+  | isJust (find (== x) xs) = uniq xs
+  | otherwise = x : uniq xs
+
+jsonEQ :: ToJSON a => a -> a -> IO ()
+jsonEQ expected actual = case diff (toJSON expected, toJSON actual) of
+  Just x -> assertFailure $ indent $ "\n" <> show x <> "\n"
+  Nothing -> pure ()
+
+zipOptional :: [Value] -> [Value] -> [(Value, Value)]
+zipOptional [] [] = []
+zipOptional (x : xs) [] = (x, Null) : zipOptional xs []
+zipOptional [] (y : ys) = (Null, y) : zipOptional [] ys
+zipOptional (x : xs) (y : ys) = (x, y) : zipOptional xs ys
diff --git a/src/Test/Morpheus/Response.hs b/src/Test/Morpheus/Response.hs
--- a/src/Test/Morpheus/Response.hs
+++ b/src/Test/Morpheus/Response.hs
@@ -18,14 +18,13 @@
     Value (..),
     decode,
     eitherDecode,
-    encode,
     fromJSON,
     object,
     (.=),
   )
 import Relude hiding (ByteString)
 import Test.Morpheus.File (FileUrl (fileName), readGQL, readJSON)
-import Test.Morpheus.Utils (requireEq)
+import Test.Morpheus.JSONDiff
 import Test.Tasty
   ( TestTree,
   )
@@ -57,7 +56,7 @@
 assertResponse f url = testCase (fileName url) $ do
   actual <- f url
   expected <- getResponse url
-  requireEq encode expected actual
+  jsonEQ expected actual
 
 runResult :: Result a -> IO a
 runResult (Success x) = pure x
