@@ -1,25 +1,24 @@
2module JSONSchema.Validator.Draft4.Any where
1module JSONSchema.Validator.Draft4.Any where
4−import Import hiding ((<>))
3+import Import hiding ((<>))
6−import Data.Aeson.TH (constructorTagModifier)
5+import Data.Aeson.TH (constructorTagModifier)
7−import Data.Char (toLower)
6+import Data.Char (toLower)
7+import qualified Data.HashMap.Strict as HM
8−import Data.List.NonEmpty (NonEmpty((:|)))
8+import Data.List.NonEmpty (NonEmpty((:|)))
9−import qualified Data.List.NonEmpty as NE
9+import qualified Data.List.NonEmpty as NE
10−import qualified Data.Scientific as SCI
10+import qualified Data.Scientific as SCI
11import Data.Semigroup
11import Data.Semigroup
12−import Data.Set (Set)
12+import Data.Set (Set)
13−import qualified Data.Set as Set
13+import qualified Data.Set as Set
14−import Data.Text.Encoding.Error (UnicodeException)
14+import Data.Text.Encoding.Error (UnicodeException)
15−import qualified JSONPointer as JP
15+import qualified JSONPointer as JP
16−import Network.HTTP.Types.URI (urlDecode)
16+import Network.HTTP.Types.URI (urlDecode)
18−import qualified JSONSchema.Validator.Utils as UT
19−import JSONSchema.Validator.Reference (BaseURI(..),
18+import JSONSchema.Validator.Reference (BaseURI(..), Scope(..),
21 URIAndFragment,
19 URIAndFragment,
22 resolveReference)
20 resolveReference)
21+import qualified JSONSchema.Validator.Utils as UT
24--------------------------------------------------
23--------------------------------------------------
@@ -135,7 +134,7 @@ data JSONPointerError
135 deriving (Eq, Show)
134 deriving (Eq, Show)
137resolveFragment
136resolveFragment
138− :: forall schema. (FromJSON schema, ToJSON schema)
137+ :: (FromJSON schema, ToJSON schema)
139 => (BaseURI -> schema -> BaseURI)
138 => (BaseURI -> schema -> BaseURI)
140 -> Scope schema
139 -> Scope schema
@@ -160,17 +159,40 @@ resolveFragment updateScope scope fragment = do
160 -- as property keys that aren't meant to change scope?
159 -- as property keys that aren't meant to change scope?
161 -- Perhaps this should be added to the language agnostic
160 -- Perhaps this should be added to the language agnostic
162 -- test suite as well.
161 -- test suite as well.
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.
163 go :: (Value, BaseURI)
167 go :: (Value, BaseURI)
164 -> JP.Token
168 -> JP.Token
165 -> Either JSONPointerError (Value, BaseURI)
169 -> Either JSONPointerError (Value, BaseURI)
166− go (lastVal, uri) tok = do
170+ go (lastVal, baseURI) tok = do
167 v <- first ResolutionError (JP.resolveToken tok lastVal)
171 v <- first ResolutionError (JP.resolveToken tok lastVal)
168− case v of
172+ newBase <- newBaseURIFromFragment updateScope baseURI v
169− Array _ -> pure (v, uri)
173+ Right (v, newBase)
171− -- PERFORMANCE: Avoid deserializing subschemas.
175+-- | Update the 'BaseURI' (the store of the current "id" value)
176+-- after resolving one token of a JSON Pointer and stepping into
178+newBaseURIFromFragment
180+ => (BaseURI -> schema -> BaseURI)
183+ -> Either JSONPointerError BaseURI
184+newBaseURIFromFragment updateScope baseURI v =
187+ let hmWithOnlyId = case HM.lookup idKey hm of
189+ Just idVal -> HM.singleton idKey idVal
172− schema <- first SubschemaDecodingError (fromJSONEither v)
190+ schema <- first SubschemaDecodingError (fromJSONEither (Object hmWithOnlyId))
173− pure (v, updateScope uri schema)
191+ Right (updateScope baseURI schema)
175--------------------------------------------------
197--------------------------------------------------