@@ -4,6 +4,7 @@ import Import hiding ((<>))
44
55import Data.Aeson.TH (constructorTagModifier)
66import Data.Char (toLower)
7+import qualified Data.HashMap.Strict as HM
78import Data.List.NonEmpty (NonEmpty((:|)))
89import qualified Data.List.NonEmpty as NE
910import qualified Data.Scientific as SCI
@@ -133,7 +134,7 @@ data JSONPointerError
133134 deriving (Eq, Show)
134135
135136resolveFragment
136− :: forall schema. (FromJSON schema, ToJSON schema)
137+ :: (FromJSON schema, ToJSON schema)
137138 => (BaseURI -> schema -> BaseURI)
138139 -> Scope schema
139140 -> Text
@@ -158,17 +159,40 @@ resolveFragment updateScope scope fragment = do
158159 -- as property keys that aren't meant to change scope?
159160 -- Perhaps this should be added to the language agnostic
160161 -- test suite as well.
162+ --
163+ -- In the meantime 'newBaseURIFromFragment' drops all keys
164+ -- from JSON objects except "id", which at least prevents
165+ -- SubschemaDecodingError in a situation where one of the
166+ -- values we step through isn't a valid schema.
161167 go :: (Value, BaseURI)
162168 -> JP.Token
163169 -> Either JSONPointerError (Value, BaseURI)
164− go (lastVal, uri) tok = do
170+ go (lastVal, baseURI) tok = do
165171 v <- first ResolutionError (JP.resolveToken tok lastVal)
166− case v of
167− Array _ -> pure (v, uri)
168− _ -> do
169− -- PERFORMANCE: Avoid deserializing subschemas.
170− schema <- first SubschemaDecodingError (fromJSONEither v)
171− pure (v, updateScope uri schema)
172+ newBase <- newBaseURIFromFragment updateScope baseURI v
173+ Right (v, newBase)
174+
175+-- | Update the 'BaseURI' (the store of the current "id" value)
176+-- after resolving one token of a JSON Pointer and stepping into
177+-- a new 'Value'.
178+newBaseURIFromFragment
179+ :: FromJSON schema
180+ => (BaseURI -> schema -> BaseURI)
181+ -> BaseURI
182+ -> Value
183+ -> Either JSONPointerError BaseURI
184+newBaseURIFromFragment updateScope baseURI v =
185+ case v of
186+ Object hm -> do
187+ let hmWithOnlyId = case HM.lookup idKey hm of
188+ Nothing -> mempty
189+ Just idVal -> HM.singleton idKey idVal
190+ schema <- first SubschemaDecodingError (fromJSONEither (Object hmWithOnlyId))
191+ Right (updateScope baseURI schema)
192+ _ -> Right baseURI
193+ where
194+ idKey :: Text
195+ idKey = "id"
172196
173197--------------------------------------------------
174198-- * enum