@@ -98,6 +98,7 @@ data Schema
98 | SchemaObject [(Symbol, Schema)]
98 | SchemaObject [(Symbol, Schema)]
99 | SchemaArray [ArrayConstraint] Schema
99 | SchemaArray [ArrayConstraint] Schema
100 | SchemaNull
100 | SchemaNull
101+ | SchemaOptional Schema
101 deriving (Generic)
102 deriving (Generic)
103data instance Sing (schema :: Schema) where
104data instance Sing (schema :: Schema) where
@@ -105,6 +106,7 @@ data instance Sing (schema :: Schema) where
105 SSchemaNumber :: Known (Sing ncs) => Sing ncs -> Sing (SchemaNumber ncs)
106 SSchemaNumber :: Known (Sing ncs) => Sing ncs -> Sing (SchemaNumber ncs)
106 SSchemaArray :: (Known (Sing acs), Known (Sing schema)) => Sing acs -> Sing schema -> Sing (SchemaArray acs schema)
107 SSchemaArray :: (Known (Sing acs), Known (Sing schema)) => Sing acs -> Sing schema -> Sing (SchemaArray acs schema)
107 SSchemaObject :: Known (Sing fields) => Sing fields -> Sing (SchemaObject fields)
108 SSchemaObject :: Known (Sing fields) => Sing fields -> Sing (SchemaObject fields)
109+ SSchemaOptional :: Known (Sing s) => Sing s -> Sing (SchemaOptional s)
108 SSchemaNull :: Sing SchemaNull
110 SSchemaNull :: Sing SchemaNull
110instance Known (Sing sl) => Known (Sing (SchemaText sl)) where
112instance Known (Sing sl) => Known (Sing (SchemaText sl)) where
@@ -117,12 +119,15 @@ instance (Known (Sing ac), Known (Sing s)) => Known (Sing (SchemaArray ac s)) wh
117 known = SSchemaArray known known
119 known = SSchemaArray known known
118instance Known (Sing stl) => Known (Sing (SchemaObject stl)) where
120instance Known (Sing stl) => Known (Sing (SchemaObject stl)) where
119 known = SSchemaObject known
121 known = SSchemaObject known
122+instance Known (Sing s) => Known (Sing (SchemaOptional s)) where
123+ known = SSchemaOptional known
121instance Eq (Sing (SchemaText cs)) where a == b = True
125instance Eq (Sing (SchemaText cs)) where a == b = True
122instance Eq (Sing (SchemaNumber cs)) where a == b = True
126instance Eq (Sing (SchemaNumber cs)) where a == b = True
123instance Eq (Sing SchemaNull) where a == b = True
127instance Eq (Sing SchemaNull) where a == b = True
124instance Eq (Sing (SchemaArray as s)) where a == b = True
128instance Eq (Sing (SchemaArray as s)) where a == b = True
125instance Eq (Sing (SchemaObject cs)) where a == b = True
129instance Eq (Sing (SchemaObject cs)) where a == b = True
130+instance Eq (Sing (SchemaOptional s)) where a == b = True
127data FieldRepr :: (Symbol, Schema) -> Type where
132data FieldRepr :: (Symbol, Schema) -> Type where
128 FieldRepr :: KnownSymbol name => JsonRepr schema -> FieldRepr '(name, schema)
133 FieldRepr :: KnownSymbol name => JsonRepr schema -> FieldRepr '(name, schema)
@@ -148,6 +153,7 @@ data JsonRepr :: Schema -> Type where
148 ReprNull :: JsonRepr SchemaNull
153 ReprNull :: JsonRepr SchemaNull
149 ReprArray :: V.Vector (JsonRepr s) -> JsonRepr (SchemaArray cs s)
154 ReprArray :: V.Vector (JsonRepr s) -> JsonRepr (SchemaArray cs s)
150 ReprObject :: Rec FieldRepr fs -> JsonRepr (SchemaObject fs)
155 ReprObject :: Rec FieldRepr fs -> JsonRepr (SchemaObject fs)
156+ ReprOptional :: Maybe (JsonRepr s) -> JsonRepr (SchemaOptional s)
152instance Show (JsonRepr (SchemaText cs)) where
158instance Show (JsonRepr (SchemaText cs)) where
153 show (ReprText t) = "ReprText " P.++ show t
159 show (ReprText t) = "ReprText " P.++ show t
@@ -163,6 +169,9 @@ instance Show (JsonRepr s) => Show (JsonRepr (SchemaArray acs s)) where
163instance RecAll FieldRepr fs Show => Show (JsonRepr (SchemaObject fs)) where
169instance RecAll FieldRepr fs Show => Show (JsonRepr (SchemaObject fs)) where
164 show (ReprObject fs) = "ReprObject " P.++ show fs
170 show (ReprObject fs) = "ReprObject " P.++ show fs
172+instance Show (JsonRepr s) => Show (JsonRepr (SchemaOptional s)) where
173+ show (ReprOptional s) = "ReprOptional " P.++ show s
166instance (Monad m, Serial m Text)
175instance (Monad m, Serial m Text)
167 => Serial m (JsonRepr (SchemaText cs)) where
176 => Serial m (JsonRepr (SchemaText cs)) where
168 series = cons1 ReprText
177 series = cons1 ReprText
@@ -178,6 +187,10 @@ instance (Serial m (V.Vector (JsonRepr s)))
178 => Serial m (JsonRepr (SchemaArray cs s)) where
187 => Serial m (JsonRepr (SchemaArray cs s)) where
179 series = cons1 ReprArray
188 series = cons1 ReprArray
190+instance (Serial m (JsonRepr s))
191+ => Serial m (JsonRepr (SchemaOptional s)) where
192+ series = cons1 ReprOptional
181instance (Monad m, Serial m (Rec FieldRepr fs))
194instance (Monad m, Serial m (Rec FieldRepr fs))
182 => Serial m (JsonRepr (SchemaObject fs)) where
195 => Serial m (JsonRepr (SchemaObject fs)) where
183 series = cons1 ReprObject
196 series = cons1 ReprObject
@@ -197,15 +210,26 @@ instance Eq (JsonRepr SchemaNull) where
197instance Eq (JsonRepr s) => Eq (JsonRepr (SchemaArray as s)) where
210instance Eq (JsonRepr s) => Eq (JsonRepr (SchemaArray as s)) where
198 ReprArray a == ReprArray b = a == b
211 ReprArray a == ReprArray b = a == b
213+instance Eq (JsonRepr s) => Eq (JsonRepr (SchemaOptional s)) where
214+ ReprOptional a == ReprOptional b = a == b
218+ => Sing (SchemaOptional s)
220+ -> Parser (Maybe (JsonRepr s))
221+fromOptional _ = parseJSON
200instance Known (Sing schema) => J.FromJSON (JsonRepr schema) where
223instance Known (Sing schema) => J.FromJSON (JsonRepr schema) where
201 parseJSON value = case known :: Sing schema of
224 parseJSON value = case known :: Sing schema of
202− SSchemaText _ -> withText "String" (pure . ReprText) value
225+ SSchemaText _ -> withText "String" (pure . ReprText) value
203− SSchemaNumber _ -> withScientific "Number" (pure . ReprNumber) value
226+ SSchemaNumber _ -> withScientific "Number" (pure . ReprNumber) value
204− SSchemaNull -> case value of
227+ SSchemaNull -> case value of
205 J.Null -> pure ReprNull
228 J.Null -> pure ReprNull
206 _ -> typeMismatch "Null" value
229 _ -> typeMismatch "Null" value
230+ so@(SSchemaOptional _) -> ReprOptional <$> fromOptional so value
207− SSchemaArray c s -> withArray "Array" (fmap ReprArray . traverse parseJSON) value
231+ SSchemaArray c s -> withArray "Array" (fmap ReprArray . traverse parseJSON) value
208− SSchemaObject fs -> do
232+ SSchemaObject fs -> do
210 demoteFields :: SList s -> H.HashMap Text J.Value -> Parser (Rec FieldRepr s)
234 demoteFields :: SList s -> H.HashMap Text J.Value -> Parser (Rec FieldRepr s)
211 demoteFields SNil h = pure RNil
235 demoteFields SNil h = pure RNil
@@ -213,29 +237,35 @@ instance Known (Sing schema) => J.FromJSON (JsonRepr schema) where
213 let fieldName = T.pack $ symbolVal (Proxy @fn)
237 let fieldName = T.pack $ symbolVal (Proxy @fn)
214 fieldRepr <- case s of
238 fieldRepr <- case s of
215 SSchemaText _ -> case H.lookup fieldName h of
239 SSchemaText _ -> case H.lookup fieldName h of
216− Just v -> FieldRepr <$> parseJSON v
240+ Just v -> FieldRepr <$> parseJSON v
217− Nothing -> fail "schematext"
241+ Nothing -> fail "schematext"
218 SSchemaNumber _ -> case H.lookup fieldName h of
242 SSchemaNumber _ -> case H.lookup fieldName h of
219− Just v -> FieldRepr <$> parseJSON v
243+ Just v -> FieldRepr <$> parseJSON v
220− Nothing -> fail "schemanumber"
244+ Nothing -> fail "schemanumber"
221 SSchemaNull -> case H.lookup fieldName h of
245 SSchemaNull -> case H.lookup fieldName h of
222− Just v -> FieldRepr <$> parseJSON v
246+ Just v -> FieldRepr <$> parseJSON v
223− Nothing -> fail "schemanull"
247+ Nothing -> fail "schemanull"
224 SSchemaArray _ _ -> case H.lookup fieldName h of
248 SSchemaArray _ _ -> case H.lookup fieldName h of
225− Just v -> FieldRepr <$> parseJSON v
249+ Just v -> FieldRepr <$> parseJSON v
226− Nothing -> fail "schemaarray"
250+ Nothing -> fail "schemaarray"
227 SSchemaObject _ -> case H.lookup fieldName h of
251 SSchemaObject _ -> case H.lookup fieldName h of
228− Just v -> FieldRepr <$> parseJSON v
252+ Just v -> FieldRepr <$> parseJSON v
229− Nothing -> fail "schemaobject"
253+ Nothing -> fail "schemaobject"
254+ SSchemaOptional s -> case H.lookup fieldName h of
255+ Just v -> FieldRepr <$> parseJSON v
256+ Nothing -> fail "schemaoptional"
230 (fieldRepr :&) <$> demoteFields tl h
257 (fieldRepr :&) <$> demoteFields tl h
231 ReprObject <$> withObject "Object" (demoteFields fs) value
258 ReprObject <$> withObject "Object" (demoteFields fs) value
233instance J.ToJSON (JsonRepr a) where
260instance J.ToJSON (JsonRepr a) where
234− toJSON ReprNull = J.Null
261+ toJSON ReprNull = J.Null
235− toJSON (ReprText t) = J.String t
262+ toJSON (ReprText t) = J.String t
236− toJSON (ReprNumber n) = J.Number n
263+ toJSON (ReprNumber n) = J.Number n
264+ toJSON (ReprOptional s) = case s of
237− toJSON (ReprArray v) = J.Array $ toJSON <$> v
267+ toJSON (ReprArray v) = J.Array $ toJSON <$> v
238− toJSON (ReprObject r) = J.Object . H.fromList . fold $ r
268+ toJSON (ReprObject r) = J.Object . H.fromList . fold $ r
240 extract :: forall name s . (KnownSymbol name)
270 extract :: forall name s . (KnownSymbol name)
241 => FieldRepr '(name, s)
271 => FieldRepr '(name, s)