fpjson.schema.schema.pp 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434
  1. {
  2. This file is part of the Free Component Library
  3. JSON Schema class
  4. Copyright (c) 2024 by Michael Van Canneyt [email protected]
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit fpjson.schema.schema;
  12. {$mode ObjFPC}
  13. {$H+}
  14. {$modeswitch typehelpers}
  15. interface
  16. uses
  17. {$IFDEF FPC_DOTTEDUNITS}
  18. System.Classes, System.SysUtils, System.Contnrs, FpJson.Data, FpJson.Schema.Types;
  19. {$ELSE}
  20. Classes, SysUtils, contnrs, fpjson, fpjson.schema.types;
  21. {$ENDIF}
  22. Type
  23. TJSONSchema = class;
  24. TJSONSchemaList = class;
  25. TJSONSchemaValidations = class;
  26. TJSONSchemaVocabulary = class;
  27. TJSONSchemaVocabularyList= class;
  28. { TJSONSchemaMetadata }
  29. TJSONSchemaMetadata = Class(TPersistent)
  30. Private
  31. FSchema: TJSONSchema;
  32. FTitle: String;
  33. FDescription: String;
  34. FDefaultValue: TJSONData;
  35. FDeprecated : Boolean;
  36. FExamples : TJSONArray;
  37. FReadOnly : Boolean;
  38. FWriteOnly : Boolean;
  39. FKeywordData : TJSONSchemaKeywords;
  40. procedure DoAddExample(Sender: TObject);
  41. procedure SetDefaultValue(AValue: TJSONData);
  42. procedure SetDeprecated(AValue: Boolean);
  43. procedure SetDescription(AValue: String);
  44. procedure SetExamples(AValue: TJSONArray);
  45. procedure SetReadOnly(AValue: Boolean);
  46. procedure SetTitle(AValue: String);
  47. procedure SetWriteOnly(AValue: Boolean);
  48. Protected
  49. procedure SetConstrained; inline;
  50. Procedure SetKeywordData(aKeyword: TJSONSchemaKeyword);
  51. Procedure UnSetKeywordData(aKeyword: TJSONSchemaKeyword);
  52. function GetOwner: TPersistent; override;
  53. // List of possible keywords for this class
  54. function Keywords : TJSONSchemaKeywords; virtual;
  55. Public
  56. procedure Assign(Source: TPersistent); override;
  57. constructor Create(aSchema : TJSONSchema); virtual;
  58. destructor Destroy; override;
  59. // List of keywords for which data is available
  60. function KeywordsWithData : TJSONSchemaKeywords; virtual;
  61. // Is this keyword set ?
  62. function HasKeywordData(aKeyword : TJSONSchemaKeyword) : boolean; virtual;
  63. property Schema : TJSONSchema Read FSchema;
  64. Published
  65. Property Title: String Read FTitle write SetTitle;
  66. Property Description: String Read FDescription write SetDescription;
  67. Property DefaultValue: TJSONData Read FDefaultValue Write SetDefaultValue;
  68. Property Deprecated: Boolean Read FDeprecated write SetDeprecated;
  69. Property Examples: TJSONArray Read FExamples Write SetExamples;
  70. Property ReadOnly: Boolean Read FReadOnly write SetReadOnly;
  71. Property WriteOnly: Boolean Read FWriteOnly write SetWriteOnly;
  72. end;
  73. { TSchemaDependentRequired }
  74. TSchemaDependentRequired = Class(TCollectionItem)
  75. private
  76. FRequired: TStrings;
  77. FURL: String;
  78. procedure SetRequired(AValue: TStrings);
  79. Public
  80. Constructor Create(ACollection: TCollection); override;
  81. Destructor Destroy; override;
  82. Procedure Assign(Source: TPersistent); override;
  83. Published
  84. Property Name : String Read FURL Write FURL;
  85. Property Required : TStrings Read FRequired Write SetRequired;
  86. end;
  87. { TSchemaDependentRequiredList }
  88. TSchemaDependentRequiredList = Class(TOwnedCollection)
  89. private
  90. function GetDependent(aIndex : integer): TSchemaDependentRequired;
  91. function GetValidations: TJSONSchemaValidations;
  92. procedure SetDependent(aIndex : integer; AValue: TSchemaDependentRequired);
  93. Public
  94. Property SchemaValidations : TJSONSchemaValidations Read GetValidations;
  95. function AddDependent(const aName : String) : TSchemaDependentRequired;
  96. Property Dependent[aIndex : integer] : TSchemaDependentRequired Read GetDependent Write SetDependent; default;
  97. end;
  98. { TJSONSchemaValidations }
  99. TJSONSchemaValidations = Class(TPersistent)
  100. private
  101. FConstValue: TJSONData;
  102. FcontentEncoding: String;
  103. FcontentMediaType: String;
  104. FcontentSchema: TJSONSchema;
  105. FDependentRequired: TSchemaDependentRequiredList;
  106. FEnum: TJSONArray;
  107. FExclusiveMaximum: Double;
  108. FExclusiveMinimum: Double;
  109. FFormat: String;
  110. FMaxContains: Integer;
  111. FMaximum: Double;
  112. FMaxItems: Cardinal;
  113. FMaxLength: Cardinal;
  114. FMaxProperties: Cardinal;
  115. FMinContains: Integer;
  116. FMinimum: Double;
  117. FMinItems: Cardinal;
  118. FMinLength: Cardinal;
  119. FMinProperties: Cardinal;
  120. FMultipleOf: Double;
  121. FPattern: String;
  122. FRequired: TStrings;
  123. FSchema: TJSONSchema;
  124. FTypes: TSchemaSimpleTypes;
  125. FUniqueItems: Boolean;
  126. FKeywordData : TJSONSchemaKeywords;
  127. procedure DoAdd(Sender: TObject);
  128. procedure DoRequiredChange(Sender: TObject);
  129. function GetContentSchema: TJSONSchema;
  130. function GetFormatValidator: TStringFormatValidator;
  131. procedure SetConstValue(AValue: TJSONData);
  132. procedure SetcontentEncoding(AValue: String);
  133. procedure SetcontentMediaType(AValue: String);
  134. procedure SetEnum(AValue: TJSONArray);
  135. procedure SetExclusiveMaximum(AValue: Double);
  136. procedure SetExclusiveMinimum(AValue: Double);
  137. procedure SetFormat(AValue: String);
  138. procedure SetFormatValidator(AValue: TStringFormatValidator);
  139. procedure SetMaxContains(AValue: Integer);
  140. procedure SetMaximum(AValue: Double);
  141. procedure SetMaxItems(AValue: Cardinal);
  142. procedure SetMaxLength(AValue: Cardinal);
  143. procedure SetMaxProperties(AValue: Cardinal);
  144. procedure SetMinContains(AValue: Integer);
  145. procedure SetMinimum(AValue: Double);
  146. procedure SetMinItems(AValue: Cardinal);
  147. procedure SetMinLength(AValue: Cardinal);
  148. procedure SetMinProperties(AValue: Cardinal);
  149. procedure SetMultipleOf(AValue: Double);
  150. procedure SetPattern(AValue: String);
  151. procedure SetRequired(AValue: TStrings);
  152. procedure SetTypes(AValue: TSchemaSimpleTypes);
  153. procedure SetUniqueItems(AValue: Boolean);
  154. Protected
  155. procedure SetConstrained;inline;
  156. procedure SetKeywordData(aKeyword: TJSONSchemaKeyword); virtual;
  157. procedure UnSetKeywordData(aKeyword: TJSONSchemaKeyword); virtual;
  158. Function CreateDependentRequired : TSchemaDependentRequiredList; virtual;
  159. function GetOwner: TPersistent; override;
  160. function Keywords : TJSONSchemaKeywords; virtual;
  161. Public
  162. procedure Assign(Source: TPersistent); override;
  163. Constructor Create(aSchema : TJSONSchema);
  164. Destructor Destroy; override;
  165. // List of keywords for which data is available
  166. function KeywordsWithData : TJSONSchemaKeywords; virtual;
  167. // Is the keyword set
  168. function HasKeywordData(aKeyword : TJSONSchemaKeyword) : Boolean; virtual;
  169. // Count types
  170. Function TypesCount : Integer;
  171. // First type (in order of TSchemaSimpleType
  172. Function GetFirstType : TSchemaSimpleType;
  173. // Owner schema
  174. property Schema : TJSONSchema Read FSchema;
  175. // type keyword
  176. property Types: TSchemaSimpleTypes read FTypes Write SetTypes;
  177. property constValue : TJSONData Read FConstValue Write SetConstValue;
  178. property Enum: TJSONArray read FEnum Write SetEnum;
  179. property ExclusiveMaximum: Double read FExclusiveMaximum write SetExclusiveMaximum;
  180. property ExclusiveMinimum: Double read FExclusiveMinimum write SetExclusiveMinimum;
  181. property Maximum: Double read FMaximum write SetMaximum;
  182. property Minimum: Double read FMinimum write SetMinimum;
  183. property MaxItems: Cardinal read FMaxItems write SetMaxItems;
  184. property MinItems: Cardinal read FMinItems write SetMinItems;
  185. property Required: TStrings read FRequired write SetRequired;
  186. property MaxLength: Cardinal read FMaxLength write SetMaxLength;
  187. property MinLength: Cardinal read FMinLength write SetMinLength;
  188. property MaxProperties: Cardinal read FMaxProperties write SetMaxProperties;
  189. property MinProperties: Cardinal read FMinProperties write SetMinProperties;
  190. property Pattern: String read FPattern write SetPattern;
  191. property UniqueItems: Boolean read FUniqueItems write SetUniqueItems;
  192. property MinContains : Integer Read FMinContains Write SetMinContains;
  193. property MaxContains : Integer Read FMaxContains Write SetMaxContains;
  194. property MultipleOf : Double Read FMultipleOf Write SetMultipleOf;
  195. Property DependentRequired : TSchemaDependentRequiredList Read FDependentRequired;
  196. // Probably better under annotations...
  197. property Format: String read FFormat write SetFormat;
  198. property FormatValidator: TStringFormatValidator read GetFormatValidator write SetFormatValidator;
  199. property contentMediaType : String read FcontentMediaType write SetcontentMediaType;
  200. property contentEncoding : String read FcontentEncoding write SetcontentEncoding;
  201. property contentSchema : TJSONSchema read GetContentSchema;
  202. end;
  203. { TJSONSchemaVocabulary }
  204. TJSONSchemaVocabulary = Class(TCollectionItem)
  205. private
  206. FEnabled: Boolean;
  207. FURL: String;
  208. Public
  209. procedure Assign(Source: TPersistent); override;
  210. function ToString : String; override;
  211. Published
  212. Property URL : String Read FURL Write FUrl;
  213. Property Enabled : Boolean Read FEnabled Write FEnabled;
  214. end;
  215. { TJSONSChemaVocabularyList }
  216. TJSONSchemaVocabularyList = Class(TOwnedCollection)
  217. private
  218. function GetSchema: TJSONSchema;
  219. function GetVocabulary(aIndex : integer): TJSONSchemaVocabulary;
  220. procedure SetVocabulary(aIndex : integer; AValue: TJSONSchemaVocabulary);
  221. Public
  222. function IndexOfVocabulary(const aURL : String) : Integer;
  223. function FindVocabulary(aURL : String) : TJSONSchemaVocabulary;
  224. Function AddVocabulary(const aURL : String) : TJSONSchemaVocabulary;
  225. Property Schema : TJSONSchema Read GetSchema;
  226. Property Vocabularies[aIndex : integer] : TJSONSchemaVocabulary Read GetVocabulary Write SetVocabulary; default;
  227. function ToString : String; overload;
  228. end;
  229. { TJsonSchema }
  230. TJsonSchema = class(TPersistent)
  231. private
  232. FAnchor: String;
  233. FComment: String;
  234. FMatchType: TSchemaMatchType;
  235. FParent: TJsonSchema;
  236. FSubSchemas : Array[TJSONSubschema] of TJSONSchema;
  237. FPatternProperties : TJsonSchemaList;
  238. FPrefixItems: TJsonSchemaList;
  239. FProperties: TJsonSchemaList;
  240. FItems: TJsonSchemaList;
  241. FAllOf: TJsonSchemaList;
  242. FAnyOf: TJsonSchemaList;
  243. FOneOf: TJsonSchemaList;
  244. FDependentSchemas: TJSONSchemaList;
  245. FDefs: TJSONSchemaList;
  246. FDynamicAnchor: String;
  247. FDynamicRef: String;
  248. FMetaData: TJSONSchemaMetadata;
  249. FName: String;
  250. FId: String;
  251. FSchema: String;
  252. FRef: String;
  253. FAdditionalProperties: TJSONSchema;
  254. FValidations: TJsonSchemaValidations;
  255. FVocabulary: TJSONSchemaVocabularyList;
  256. FUnknownKeywordData : TJSONObject;
  257. FChildren : TFPList;
  258. FKeywordData : TJSONSchemaKeywords;
  259. function GetAdditionalProperties: TJSONSchema;
  260. function GetChildSchema(aIndex : Integer): TJSONSchema;
  261. function GetChildSchemaCount: Integer;
  262. function GetDependentSchemas: TJSONSchemaList;
  263. function GetNamedList(const aName: string): TJSONSchemaList;
  264. function GetPatternProperties: TJsonSchemaList;
  265. function GetUnknownKeywordData: TJSONObject;
  266. procedure SetMetadata(AValue: TJSONSchemaMetadata);
  267. procedure SetString(AIndex: Integer; AValue: String);
  268. procedure SetValidations(AValue: TJsonSchemaValidations);
  269. procedure SetVocabulary(AValue: TJSONSchemaVocabularyList);
  270. protected
  271. procedure SetKeyWordData(akeyWord : TJSONSchemaKeyword);
  272. procedure UnsetKeyWordData(akeyWord : TJSONSchemaKeyword);
  273. function GetSubSchema(aIndex : Integer) : TJSONSchema;
  274. function CreateVocabulary : TJSONSchemaVocabularyList; virtual;
  275. function CreateMetadata: TJSONSchemaMetadata; virtual;
  276. function CreateValidations: TJsonSchemaValidations; virtual;
  277. procedure CheckConstrained;
  278. function GetPath: String; virtual;
  279. public
  280. constructor Create(AParent: TJsonSchema);
  281. constructor Create;
  282. destructor Destroy; override;
  283. // Check if there is data for a given keyword.
  284. Function HasKeywordData(aKeyword : TJSONSchemaKeyword) : Boolean;
  285. // All set keywords
  286. Function KeywordsWithData : TJSONSchemaKeywords;
  287. // Create child schema with given name
  288. function CreateChildSchema(aName : string): TJsonSchema; overload;
  289. // Create child schema with name equal to keyword.
  290. function CreateChildSchema(aKeyword : TJSONSchemaKeyword): TJsonSchema; overload;
  291. // Create unnamed child schema
  292. function CreateChildSchema: TJsonSchema; virtual;
  293. // Toplevel schema (follows parent)
  294. Function RootSchema: TJSONSchema;
  295. // Find schema using schema-local $Ref URI
  296. function Find(const aPath : String) : TJSONSchema;
  297. // Find index of direct child schema with given name
  298. function IndexOfChild(const aName: String): Integer;
  299. // Find direct child schema with given name
  300. function FindChild(const aName: String): TJSONSchema;
  301. // Enumerate child schemas (named and unnamed)
  302. property ChildSchemas[aIndex : Integer] : TJSONSchema Read GetChildSchema;
  303. // Number of child schemas (named and unnamed)
  304. property ChildSchemaCount : Integer Read GetChildSchemaCount;
  305. // Parent schema
  306. Property Parent : TJSONSchema Read FParent;
  307. // Path till root schema.
  308. Property Path : String Read GetPath;
  309. // Name of current schema in parent.
  310. property Name: String read FName write FName;
  311. { Core vocabulary }
  312. // Was the schema read as True/False/Object
  313. property MatchType : TSchemaMatchType Read FMatchType Write FMatchType;
  314. // Identifier of used JSON schema
  315. property Schema: String Index Ord(jskSchema) read FSchema write SetString;
  316. // ID of this schema
  317. property Id: String Index Ord(jskID) read FId write SetString;
  318. // $ref
  319. property Ref: String Index Ord(jskRef) read FRef write SetString;
  320. // $comment
  321. property Comment: String Index Ord(jskComment) read FComment write SetString;
  322. // $anchor
  323. property Anchor: String Index Ord(jskAnchor) read FAnchor write SetString;
  324. // $dynamicAnchor
  325. property DynamicAnchor: String Index Ord(jskDynamicAnchor) read FDynamicAnchor write SetString;
  326. // $dynamicRef
  327. property DynamicRef: String Index Ord(jskDynamicRef) read FDynamicRef write SetString;
  328. // $vocabulary
  329. property Vocabulary : TJSONSchemaVocabularyList Read FVocabulary Write SetVocabulary;
  330. // $defs
  331. property Defs: TJSONSchemaList read FDefs;
  332. // Metadata vocabulary keywords
  333. Property MetaData : TJSONSchemaMetadata Read FMetaData Write SetMetadata;
  334. // Validations vocabulary keywords
  335. Property Validations : TJsonSchemaValidations Read FValidations Write SetValidations;
  336. // Applicator vocabulary keywords
  337. // allOf keyword
  338. property AllOf: TJsonSchemaList read FAllOf;
  339. // anyOf keyword
  340. property AnyOf: TJsonSchemaList read FAnyOf;
  341. // OneOf keyword
  342. property OneOf: TJsonSchemaList read FOneOf;
  343. // Not keyword
  344. property NotSchema: TJsonSchema index Ord(ssNot) read GetSubSchema;
  345. // if keyword
  346. property IfSchema: TJsonSchema index Ord(ssIf) read GetSubSchema;
  347. // Then keyword
  348. property ThenSchema: TJsonSchema index Ord(ssThen) read GetSubSchema;
  349. // Else keyword
  350. property ElseSchema: TJsonSchema index Ord(ssElse) read GetSubSchema;
  351. // properties keyword
  352. property Properties: TJsonSchemaList read FProperties;
  353. // items keyword.
  354. // Declared in draft 2020-12 as schema, but we keep it a List, so we can handle earlier drafts.
  355. property Items: TJsonSchemaList read FItems;
  356. // prefixItems keyword
  357. property PrefixItems: TJsonSchemaList read FPrefixItems;
  358. // patternProperties keyword
  359. property PatternProperties: TJsonSchemaList Read GetPatternProperties;
  360. // propertyNames keyword
  361. property PropertyNames: TJsonSchema index Ord(ssPropertyNames) read GetSubSchema;
  362. // additionalProperties keyword
  363. property AdditionalProperties: TJSONSchema index Ord(ssAdditionalProperties) read GetSubschema;
  364. // dependentSchemas keyw
  365. property DependentSchemas: TJSONSchemaList read GetDependentSchemas;
  366. // contains keyword
  367. property Contains: TJsonSchema Index Ord(ssContains) read GetSubSchema;
  368. // unevaluatedItems keyword
  369. property UnevaluatedItems : TJSONSchema Index Ord(ssUnevaluatedItems) read GetSubSchema;
  370. // unevaluatedProperties keyword
  371. property UnevaluatedProperties : TJSONSchema Index Ord(ssUnevaluatedProperties) read GetSubSchema;
  372. // Not in any vocabulary:
  373. // Can be filled by reader with unknown properties.
  374. property UnknownKeywordData : TJSONObject Read GetUnknownKeywordData;
  375. end;
  376. TJsonSchemaClass = Class of TJsonSchema;
  377. { TJSONSchemaList }
  378. TJSONSchemaList = Class(TFPObjectList)
  379. private
  380. FKeyword: TJSONSchemaKeyword;
  381. FSchemaOwner: TJSONSchema;
  382. function GetSchema(aIndex : integer): TJSONSchema;
  383. procedure SetSchema(aIndex : integer; AValue: TJSONSchema);
  384. Public
  385. Constructor Create(aOwner : TJSONSchema; aKeyWord : TJSONSchemaKeyword); overload;
  386. Function FindIDOrNames(aPath : String) : TJSONSchema;
  387. Function Add(const aName : string = ''): TJSONSchema; overload;
  388. Function Add(Schema : TJSONSchema): Integer; overload;
  389. property SchemaOwner : TJSONSchema Read FSchemaOwner;
  390. property Keyword : TJSONSchemaKeyword Read FKeyword;
  391. Property Schemas[aIndex : integer] : TJSONSchema Read GetSchema Write SetSchema; default;
  392. end;
  393. implementation
  394. { TJSONSchemaMetadata }
  395. procedure TJSONSchemaMetadata.SetConstrained;
  396. begin
  397. if Assigned(Schema) then
  398. Schema.MatchType:=smConstrained;
  399. end;
  400. procedure TJSONSchemaMetadata.DoAddExample(Sender: TObject);
  401. begin
  402. SetConstrained;
  403. end;
  404. procedure TJSONSchemaMetadata.SetDefaultValue(AValue: TJSONData);
  405. begin
  406. if FDefaultValue=AValue then Exit;
  407. FreeAndNil(FDefaultValue);
  408. FDefaultValue:=AValue;
  409. if Assigned(FDefaultValue) then
  410. SetKeywordData(jskDefault);
  411. end;
  412. procedure TJSONSchemaMetadata.SetDeprecated(AValue: Boolean);
  413. begin
  414. SetKeywordData(jskDeprecated);
  415. if FDeprecated=AValue then Exit;
  416. FDeprecated:=AValue;
  417. end;
  418. procedure TJSONSchemaMetadata.SetDescription(AValue: String);
  419. begin
  420. if FDescription=AValue then Exit;
  421. FDescription:=AValue;
  422. SetKeywordData(jskDescription);
  423. end;
  424. procedure TJSONSchemaMetadata.SetExamples(AValue: TJSONArray);
  425. begin
  426. if FExamples=AValue then Exit;
  427. FreeAndNil(FExamples);
  428. FExamples:=AValue;
  429. if FExamples=Nil then
  430. FExamples:=TJSONArray.Create;
  431. SetKeywordData(jskExamples);
  432. end;
  433. procedure TJSONSchemaMetadata.SetReadOnly(AValue: Boolean);
  434. begin
  435. SetKeywordData(jskReadOnly);
  436. if FReadOnly=AValue then Exit;
  437. FReadOnly:=AValue;
  438. end;
  439. procedure TJSONSchemaMetadata.SetTitle(AValue: String);
  440. begin
  441. if FTitle=AValue then Exit;
  442. FTitle:=AValue;
  443. SetKeywordData(jskTitle);
  444. end;
  445. procedure TJSONSchemaMetadata.SetWriteOnly(AValue: Boolean);
  446. begin
  447. SetKeywordData(jskWriteOnly);
  448. if FWriteOnly=AValue then Exit;
  449. FWriteOnly:=AValue;
  450. end;
  451. procedure TJSONSchemaMetadata.SetKeywordData(aKeyword: TJSONSchemaKeyword);
  452. begin
  453. Include(FKeywordData,aKeyword);
  454. SetConstrained;
  455. end;
  456. procedure TJSONSchemaMetadata.UnSetKeywordData(aKeyword: TJSONSchemaKeyword);
  457. begin
  458. Exclude(FKeywordData,aKeyword);
  459. if Assigned(Schema) then
  460. Schema.CheckConstrained;
  461. end;
  462. procedure TJSONSchemaMetadata.Assign(Source: TPersistent);
  463. var
  464. aSource: TJSONSchemaMetadata absolute source;
  465. begin
  466. if Source is TJSONSchemaMetadata then
  467. begin
  468. FKeywordData:=[];
  469. WriteOnly:=aSource.FWriteOnly;
  470. Title:=aSource.FTitle;
  471. ReadOnly:=aSource.FReadOnly;
  472. Description:=aSource.FDescription;
  473. Deprecated:=aSource.FDeprecated;
  474. DefaultValue:=aSource.DefaultValue.Clone;
  475. Examples:=aSource.Examples.Clone as TJSONArray;
  476. end
  477. else
  478. inherited Assign(Source);
  479. end;
  480. constructor TJSONSchemaMetadata.Create(aSchema: TJSONSchema);
  481. begin
  482. FSchema:=aSchema;
  483. Fexamples:=TJSONArray.Create;
  484. end;
  485. destructor TJSONSchemaMetadata.Destroy;
  486. begin
  487. inherited Destroy;
  488. FreeAndNil(FDefaultValue);
  489. FreeAndNil(FExamples);
  490. end;
  491. function TJSONSchemaMetadata.GetOwner: TPersistent;
  492. begin
  493. Result:=FSchema;
  494. end;
  495. function TJSONSchemaMetadata.Keywords: TJSONSchemaKeywords;
  496. begin
  497. Result:=MetadataKeywords;
  498. end;
  499. function TJSONSchemaMetadata.KeywordsWithData: TJSONSchemaKeywords;
  500. var
  501. K : TJSONSchemaKeyword;
  502. begin
  503. Result:=[];
  504. For K in Keywords do
  505. if HasKeywordData(K) then
  506. Include(Result,K);
  507. end;
  508. function TJSONSchemaMetadata.HasKeywordData(aKeyword: TJSONSchemaKeyword): boolean;
  509. begin
  510. Case aKeyword of
  511. jskDefault: Result:=Assigned(FDefaultValue);
  512. jskExamples : Result:=(FExamples.Count>0);
  513. else
  514. Result:=aKeyword in FKeywordData;
  515. end;
  516. end;
  517. { TSchemaDependentRequired }
  518. procedure TSchemaDependentRequired.SetRequired(AValue: TStrings);
  519. begin
  520. if FRequired=AValue then Exit;
  521. FRequired.Assign(AValue);
  522. end;
  523. constructor TSchemaDependentRequired.Create(ACollection: TCollection);
  524. begin
  525. inherited Create(ACollection);
  526. FRequired:=TStringList.Create;
  527. end;
  528. destructor TSchemaDependentRequired.Destroy;
  529. begin
  530. FreeAndNil(FRequired);
  531. inherited Destroy;
  532. end;
  533. procedure TSchemaDependentRequired.Assign(Source: TPersistent);
  534. var
  535. Src :TSchemaDependentRequired absolute Source;
  536. begin
  537. if Source is TSchemaDependentRequired then
  538. begin
  539. Name:=Src.Name;
  540. Required.Assign(Src.Required);
  541. end
  542. else
  543. inherited Assign(Source);
  544. end;
  545. { TSchemaDependentRequiredList }
  546. function TSchemaDependentRequiredList.GetDependent(aIndex : integer): TSchemaDependentRequired;
  547. begin
  548. Result:=Items[aIndex] as TSchemaDependentRequired;
  549. end;
  550. function TSchemaDependentRequiredList.GetValidations: TJSONSchemaValidations;
  551. begin
  552. if owner is TJSONSchemaValidations then
  553. Result:=TJSONSchemaValidations(Owner)
  554. else
  555. Result:=Nil;
  556. end;
  557. procedure TSchemaDependentRequiredList.SetDependent(aIndex : integer; AValue: TSchemaDependentRequired);
  558. begin
  559. Items[aIndex]:=aValue;
  560. end;
  561. function TSchemaDependentRequiredList.AddDependent(const aName: String): TSchemaDependentRequired;
  562. begin
  563. Result:=Add as TSchemaDependentRequired;
  564. Result.Name:=aName;
  565. if Assigned(SchemaValidations) and Assigned(SchemaValidations.Schema) then
  566. SchemaValidations.Schema.MatchType:=smConstrained;
  567. end;
  568. { TJsonSchemaValidations }
  569. procedure TJSONSchemaValidations.SetConstValue(AValue: TJSONData);
  570. begin
  571. if FConstValue=AValue then Exit;
  572. FreeAndNil(FConstValue);
  573. FConstValue:=AValue;
  574. SetKeyWordData(jskConst);
  575. end;
  576. procedure TJSONSchemaValidations.SetcontentEncoding(AValue: String);
  577. begin
  578. if FcontentEncoding=AValue then Exit;
  579. FcontentEncoding:=AValue;
  580. SetKeywordData(jskContentEncoding);
  581. end;
  582. procedure TJSONSchemaValidations.SetcontentMediaType(AValue: String);
  583. begin
  584. if FcontentMediaType=AValue then Exit;
  585. FcontentMediaType:=AValue;
  586. SetKeywordData(jskContentMediaType);
  587. end;
  588. procedure TJSONSchemaValidations.SetEnum(AValue: TJSONArray);
  589. begin
  590. if FEnum=AValue then Exit;
  591. FreeAndNil(FEnum);
  592. FEnum:=AValue;
  593. if FEnum=Nil then
  594. FEnum:=TJSONArray.Create;
  595. SetKeywordData(jskEnum);
  596. end;
  597. procedure TJSONSchemaValidations.SetExclusiveMaximum(AValue: Double);
  598. begin
  599. if FExclusiveMaximum=AValue then Exit;
  600. FExclusiveMaximum:=AValue;
  601. SetKeywordData(jskExclusiveMaximum);
  602. end;
  603. procedure TJSONSchemaValidations.SetExclusiveMinimum(AValue: Double);
  604. begin
  605. if FExclusiveMinimum=AValue then Exit;
  606. FExclusiveMinimum:=AValue;
  607. SetKeywordData(jskExclusiveMinimum);
  608. end;
  609. procedure TJSONSchemaValidations.SetFormat(AValue: String);
  610. begin
  611. if FFormat=AValue then Exit;
  612. FFormat:=AValue;
  613. SetKeywordData(jskFormat);
  614. end;
  615. procedure TJSONSchemaValidations.SetFormatValidator(AValue: TStringFormatValidator);
  616. begin
  617. Format:=aValue.AsString;
  618. end;
  619. procedure TJSONSchemaValidations.SetMaxContains(AValue: Integer);
  620. begin
  621. if FMaxContains=AValue then Exit;
  622. FMaxContains:=AValue;
  623. SetKeywordData(jskMaxContains);
  624. end;
  625. procedure TJSONSchemaValidations.SetMaximum(AValue: Double);
  626. begin
  627. if FMaximum=AValue then Exit;
  628. FMaximum:=AValue;
  629. SetKeywordData(jskMaximum);
  630. end;
  631. procedure TJSONSchemaValidations.SetMaxItems(AValue: Cardinal);
  632. begin
  633. if FMaxItems=AValue then Exit;
  634. FMaxItems:=AValue;
  635. SetKeywordData(jskMaxItems);
  636. end;
  637. procedure TJSONSchemaValidations.SetMaxLength(AValue: Cardinal);
  638. begin
  639. if FMaxLength=AValue then Exit;
  640. FMaxLength:=AValue;
  641. SetKeywordData(jskMaxLength);
  642. end;
  643. procedure TJSONSchemaValidations.SetMaxProperties(AValue: Cardinal);
  644. begin
  645. if FMaxProperties=AValue then Exit;
  646. FMaxProperties:=AValue;
  647. SetKeywordData(jskMaxProperties);
  648. end;
  649. procedure TJSONSchemaValidations.SetMinContains(AValue: Integer);
  650. begin
  651. if FMinContains=AValue then Exit;
  652. FMinContains:=AValue;
  653. SetKeywordData(jskMinContains);
  654. end;
  655. procedure TJSONSchemaValidations.SetMinimum(AValue: Double);
  656. begin
  657. if FMinimum=AValue then Exit;
  658. FMinimum:=AValue;
  659. SetKeywordData(jskMinimum);
  660. end;
  661. procedure TJSONSchemaValidations.SetMinItems(AValue: Cardinal);
  662. begin
  663. if FMinItems=AValue then Exit;
  664. FMinItems:=AValue;
  665. SetKeywordData(jskMinItems);
  666. end;
  667. procedure TJSONSchemaValidations.SetMinLength(AValue: Cardinal);
  668. begin
  669. if FMinLength=AValue then Exit;
  670. FMinLength:=AValue;
  671. SetKeywordData(jskMinLength);
  672. end;
  673. procedure TJSONSchemaValidations.SetMinProperties(AValue: Cardinal);
  674. begin
  675. if FMinProperties=AValue then Exit;
  676. FMinProperties:=AValue;
  677. SetKeywordData(jskMinProperties);
  678. end;
  679. procedure TJSONSchemaValidations.SetMultipleOf(AValue: Double);
  680. begin
  681. if FMultipleOf=AValue then Exit;
  682. FMultipleOf:=AValue;
  683. SetKeywordData(jskMultipleOf);
  684. end;
  685. procedure TJSONSchemaValidations.SetPattern(AValue: String);
  686. begin
  687. if FPattern=AValue then Exit;
  688. FPattern:=AValue;
  689. SetKeywordData(jskPattern);
  690. end;
  691. procedure TJSONSchemaValidations.SetRequired(AValue: TStrings);
  692. begin
  693. if FRequired=AValue then Exit;
  694. FRequired.Assign(AValue);
  695. SetKeywordData(jskRequired);
  696. end;
  697. procedure TJSONSchemaValidations.SetTypes(AValue: TSchemaSimpleTypes);
  698. begin
  699. if FTypes=AValue then Exit;
  700. FTypes:=AValue;
  701. SetKeywordData(jskType);
  702. end;
  703. procedure TJSONSchemaValidations.SetUniqueItems(AValue: Boolean);
  704. begin
  705. if FUniqueItems=AValue then Exit;
  706. FUniqueItems:=AValue;
  707. SetKeywordData(jskUniqueItems);
  708. end;
  709. procedure TJSONSchemaValidations.SetConstrained;
  710. begin
  711. if Assigned(Schema) then
  712. Schema.MatchType:=smConstrained;
  713. end;
  714. procedure TJSONSchemaValidations.SetKeywordData(aKeyword: TJSONSchemaKeyword);
  715. begin
  716. Include(FKeywordData,aKeyword);
  717. SetConstrained;
  718. end;
  719. procedure TJSONSchemaValidations.UnSetKeywordData(aKeyword: TJSONSchemaKeyword);
  720. begin
  721. Exclude(FKeywordData,aKeyword);
  722. end;
  723. function TJSONSchemaValidations.GetContentSchema: TJSONSchema;
  724. begin
  725. if FcontentSchema=Nil then
  726. begin
  727. if Assigned(Schema) then
  728. FcontentSchema:=Schema.CreateChildSchema(jskContentSchema)
  729. else
  730. begin
  731. FContentSchema:=TJSONSchema.Create(Nil);
  732. FContentSchema.Name:=jskContentSchema.AsString;
  733. end;
  734. SetConstrained;
  735. end;
  736. Result:=FcontentSchema;
  737. end;
  738. procedure TJSONSchemaValidations.DoRequiredChange(Sender: TObject);
  739. begin
  740. if HasKeywordData(jskRequired) then
  741. SetConstrained;
  742. end;
  743. procedure TJSONSchemaValidations.DoAdd(Sender: TObject);
  744. begin
  745. SetConstrained;
  746. end;
  747. function TJSONSchemaValidations.GetFormatValidator: TStringFormatValidator;
  748. begin
  749. Result:=TStringFormatValidator.FromString(Format);
  750. end;
  751. constructor TJSONSchemaValidations.Create(aSchema: TJSONSchema);
  752. begin
  753. FSchema:=aSchema;
  754. FRequired:=TStringList.Create;
  755. TStringList(FRequired).OnChange:=@DoRequiredChange;
  756. FEnum:=TJSONArray.Create;
  757. FDependentRequired:=CreateDependentRequired;
  758. end;
  759. destructor TJSONSchemaValidations.Destroy;
  760. begin
  761. ConstValue:=Nil;
  762. FreeAndNil(FDependentRequired);
  763. FreeAndNil(FRequired);
  764. FreeAndNil(FEnum);
  765. FreeAndNil(FcontentSchema);
  766. inherited Destroy;
  767. end;
  768. function TJSONSchemaValidations.KeywordsWithData: TJSONSchemaKeywords;
  769. var
  770. K : TJSONSchemaKeyword;
  771. begin
  772. Result:=[];
  773. For K in Keywords do
  774. if HasKeyWordData(K) then
  775. Include(Result,K);
  776. end;
  777. function TJSONSchemaValidations.HasKeywordData(aKeyword: TJSONSchemaKeyword): Boolean;
  778. begin
  779. case aKeyword of
  780. jskEnum : Result:=Assigned(FEnum) and (FEnum.Count>0);
  781. jskRequired : Result:=Assigned(FRequired) and (Required.Count>0);
  782. jskDependentRequired : Result:=Assigned(FDependentRequired) and (FDependentRequired.Count>0);
  783. jskContentSchema : Result:=Assigned(FContentSchema);
  784. else
  785. Result:=aKeyword in FKeywordData
  786. end;
  787. end;
  788. function TJSONSchemaValidations.TypesCount: Integer;
  789. var
  790. T : TSchemaSimpleType;
  791. begin
  792. Result:=0;
  793. For T in TSchemaSimpleType do
  794. if T in Types then
  795. Inc(Result);
  796. end;
  797. function TJSONSchemaValidations.GetFirstType: TSchemaSimpleType;
  798. var
  799. T : TSchemaSimpleType;
  800. begin
  801. Result:=sstNone;
  802. For T in TSchemaSimpleType do
  803. if T in Types then
  804. Exit(T);
  805. end;
  806. { TJSONSChemaVocabulary }
  807. procedure TJSONSchemaVocabulary.Assign(Source: TPersistent);
  808. var
  809. aSource: TJSONSChemaVocabulary absolute source;
  810. begin
  811. if Source is TJSONSChemaVocabulary then
  812. begin
  813. URL:=aSource.URL;
  814. Enabled:=aSource.Enabled;
  815. end
  816. else
  817. inherited Assign(Source);
  818. end;
  819. function TJSONSchemaVocabulary.ToString: String;
  820. begin
  821. Result:=URL+': '+BoolToStr(Enabled,'True','False');
  822. end;
  823. { TJSONSChemaVocabularyList }
  824. function TJSONSchemaVocabularyList.GetSchema: TJSONSchema;
  825. begin
  826. if Owner is TJSONSchema then
  827. Result:=TJSONSchema(Owner)
  828. else
  829. Result:=Nil;
  830. end;
  831. function TJSONSchemaVocabularyList.GetVocabulary(aIndex : integer): TJSONSchemaVocabulary;
  832. begin
  833. Result:=TJSONSchemaVocabulary(Items[aIndex])
  834. end;
  835. procedure TJSONSchemaVocabularyList.SetVocabulary(aIndex : integer; AValue: TJSONSchemaVocabulary);
  836. begin
  837. Items[aIndex]:=aValue;
  838. end;
  839. function TJSONSchemaVocabularyList.IndexOfVocabulary(const aURL: String): Integer;
  840. begin
  841. Result:=Count-1;
  842. While (Result>=0) and not SameText(aURL,GetVocabulary(Result).URL) do
  843. Dec(Result);
  844. end;
  845. function TJSONSchemaVocabularyList.FindVocabulary(aURL: String): TJSONSchemaVocabulary;
  846. var
  847. Idx : Integer;
  848. begin
  849. Idx:=IndexOfVocabulary(aURL);
  850. if Idx=-1 then
  851. Result:=Nil
  852. else
  853. Result:=GetVocabulary(Idx);
  854. end;
  855. function TJSONSchemaVocabularyList.AddVocabulary(const aURL: String): TJSONSchemaVocabulary;
  856. begin
  857. Result:=add as TJSONSchemaVocabulary;
  858. Result.URL:=aURL;
  859. if assigned(Schema) then
  860. Schema.MatchType:=smConstrained;
  861. end;
  862. function TJSONSchemaVocabularyList.ToString: String;
  863. var
  864. I : Integer;
  865. begin
  866. Result:='';
  867. For I:=0 to Count-1 do
  868. if Vocabularies[I].Enabled then
  869. Result:=Result+Vocabularies[I].ToString;
  870. end;
  871. { TJsonSchema }
  872. function TJsonSchema.GetAdditionalProperties: TJSONSchema;
  873. begin
  874. if Not Assigned(FAdditionalproperties) then
  875. FAdditionalproperties:=CreateChildSchema(jskAdditionalProperties);
  876. Result:=FAdditionalproperties;
  877. end;
  878. function TJsonSchema.GetChildSchema(aIndex : Integer): TJSONSchema;
  879. begin
  880. Result:=TJSONSchema(FChildren[aIndex]);
  881. end;
  882. function TJsonSchema.GetChildSchemaCount: Integer;
  883. begin
  884. Result:=FChildren.Count;
  885. end;
  886. function TJsonSchema.GetDependentSchemas: TJSONSchemaList;
  887. begin
  888. if FDependentSchemas=Nil then
  889. FDependentSchemas:=TJSONSchemaList.Create(Self,jskDependentSchemas);
  890. Result:=FDependentSchemas;
  891. end;
  892. function TJsonSchema.GetPatternProperties: TJsonSchemaList;
  893. begin
  894. if FPatternProperties=Nil then
  895. FPatternProperties:=TJSONSchemaList.Create(Self,jskPatternProperties);
  896. Result:=FPatternProperties;
  897. end;
  898. function TJsonSchema.GetUnknownKeywordData: TJSONObject;
  899. begin
  900. if FUnknownKeywordData=Nil then
  901. FUnknownKeywordData:=TJSONObject.Create;
  902. Result:=FUnknownKeywordData;
  903. end;
  904. procedure TJsonSchema.SetMetadata(AValue: TJSONSchemaMetadata);
  905. begin
  906. if FMetaData=AValue then Exit;
  907. FMetaData.Assign(AValue);
  908. end;
  909. procedure TJsonSchema.SetString(AIndex: Integer; AValue: String);
  910. var
  911. KW : TJSONSchemaKeyword;
  912. begin
  913. kw:=TJSONSchemaKeyword(aIndex);
  914. SetKeyWordData(kw);
  915. Case kw of
  916. jskSchema: FSchema:=aValue;
  917. jskId: FId:=aValue;
  918. jskRef: FRef:=aValue;
  919. jskComment: FComment:=aValue;
  920. jskAnchor: FAnchor:=aValue;
  921. jskDynamicAnchor: FDynamicAnchor:=aValue;
  922. jskDynamicRef: FDynamicRef:=aValue;
  923. end;
  924. end;
  925. procedure TJsonSchema.SetValidations(AValue: TJsonSchemaValidations);
  926. begin
  927. if FValidations=AValue then Exit;
  928. FValidations.Assign(AValue);
  929. end;
  930. procedure TJsonSchema.SetVocabulary(AValue: TJSONSchemaVocabularyList);
  931. begin
  932. if FVocabulary=AValue then Exit;
  933. FVocabulary.Assign(AValue);
  934. end;
  935. procedure TJsonSchema.SetKeyWordData(akeyWord: TJSONSchemaKeyword);
  936. begin
  937. Include(FKeywordData,aKeyword);
  938. FMatchType:=smConstrained;
  939. end;
  940. procedure TJsonSchema.UnsetKeyWordData(akeyWord: TJSONSchemaKeyword);
  941. begin
  942. Exclude(FKeywordData,aKeyword);
  943. end;
  944. function TJsonSchema.GetSubSchema(aIndex: Integer): TJSONSchema;
  945. var
  946. SS : TJSONSubSchema;
  947. begin
  948. SS:=TJSONSubSchema(aindex);
  949. if Not Assigned(FSubSchemas[SS]) then
  950. begin
  951. FSubSchemas[SS]:=CreateChildSchema(SS.AsSchemaKeyword);
  952. SetKeyWordData(SS.AsSchemaKeyword);
  953. end;
  954. Result:=FSubSchemas[SS];
  955. end;
  956. function TJsonSchema.CreateChildSchema(aName: string): TJsonSchema;
  957. begin
  958. Result:=CreateChildSchema();
  959. Result.Name:=aName;
  960. end;
  961. function TJsonSchema.CreateChildSchema(aKeyword: TJSONSchemaKeyword): TJsonSchema;
  962. begin
  963. Result:=CreateChildSchema(aKeyWord.AsString);
  964. end;
  965. function TJsonSchema.CreateVocabulary: TJSONSchemaVocabularyList;
  966. begin
  967. Result:=TJSONSchemaVocabularyList.Create(Self,TJSONSchemaVocabulary);
  968. end;
  969. constructor TJsonSchema.Create(AParent: TJsonSchema);
  970. begin
  971. FParent:=aParent;
  972. if Assigned(FParent) then
  973. FParent.FChildren.Add(Self);
  974. FDefs:=TJsonSchemaList.Create(Self,jskDefs);
  975. FItems:=TJsonSchemaList.Create(Self,jskItems);
  976. FAllOf:=TJsonSchemaList.Create(Self,jskAllof);
  977. FAnyOf:=TJsonSchemaList.Create(Self,jskAnyOf);
  978. FOneOf:=TJsonSchemaList.Create(Self,jskOneOf);
  979. FProperties:=TJsonSchemaList.Create(Self,jskProperties);
  980. FPrefixItems:=TJsonSchemaList.Create(Self,jskPrefixItems);
  981. FVocabulary:=CreateVocabulary;
  982. FMetaData:=CreateMetaData;
  983. FValidations:=CreateValidations;
  984. FChildren:=TFPList.Create;
  985. end;
  986. constructor TJsonSchema.Create;
  987. begin
  988. Create(Nil);
  989. end;
  990. destructor TJsonSchema.Destroy;
  991. var
  992. SS :TJSONSubschema;
  993. I : Integer;
  994. begin
  995. if Assigned(FParent) then
  996. FParent.FChildren.Remove(Self);
  997. For I:=0 to FChildren.Count-1 do
  998. TJsonSchema(FChildren[I]).FParent:=Nil;
  999. For SS in TJSONSubschema do
  1000. FreeAndNil(FSubSchemas[SS]);
  1001. FreeAndNil(FValidations);
  1002. FreeAndNil(FItems);
  1003. FreeAndNil(FAllOf);
  1004. FreeAndNil(FAnyOf);
  1005. FreeAndNil(FOneOf);
  1006. FreeAndNil(FProperties);
  1007. FreeAndNil(FPrefixItems);
  1008. FreeAndNil(FVocabulary);
  1009. FreeAndNil(FMetaData);
  1010. FreeAndNil(FPrefixItems);
  1011. FreeAndNil(FAdditionalProperties);
  1012. FreeAndNil(FPatternProperties);
  1013. FreeAndNil(FDependentSchemas);
  1014. FreeAndNil(FDefs);
  1015. FreeAndNil(FUnknownKeywordData);
  1016. FreeAndNil(FChildren);
  1017. inherited Destroy;
  1018. end;
  1019. function TJsonSchema.HasKeywordData(aKeyword: TJSONSchemaKeyword): Boolean;
  1020. begin
  1021. if aKeyword in Validations.Keywords then
  1022. Result:=Validations.HasKeywordData(aKeyWord)
  1023. else if aKeyword in MetaData.Keywords then
  1024. Result:=MetaData.HasKeywordData(aKeyWord)
  1025. else
  1026. begin
  1027. Case aKeyword of
  1028. jskPrefixItems: Result:=FPrefixItems.Count>0;
  1029. jskProperties : Result:=FProperties.Count>0;
  1030. jskItems : Result:=FItems.Count>0;
  1031. jskAllOf : Result:=FAllOf.Count>0;
  1032. jskAnyOf : Result:=FAnyOf.Count>0;
  1033. jskOneOf : Result:=FOneOf.Count>0;
  1034. jskDependentSchemas: Result:=Assigned(FDependentSchemas) and (FDependentSchemas.Count>0);
  1035. jskPatternProperties: Result:=Assigned(FPatternProperties) and (FPatternProperties.Count>0);
  1036. jskDefs : Result:=FDefs.Count>0;
  1037. jskVocabulary : Result:=Assigned(FVocabulary) and (FVocabulary.Count>0);
  1038. else
  1039. Result:=aKeyword in FKeywordData;
  1040. end;
  1041. end;
  1042. end;
  1043. function TJsonSchema.KeywordsWithData: TJSONSchemaKeywords;
  1044. begin
  1045. Result:=FKeywordData+Validations.FKeywordData+MetaData.Keywords;
  1046. end;
  1047. function TJSONSchemaValidations.CreateDependentRequired: TSchemaDependentRequiredList;
  1048. begin
  1049. Result:=TSchemaDependentRequiredList.Create(Self,TSchemaDependentRequired);
  1050. end;
  1051. function TJSONSchemaValidations.GetOwner: TPersistent;
  1052. begin
  1053. Result:=FSchema;
  1054. end;
  1055. function TJSONSchemaValidations.Keywords: TJSONSchemaKeywords;
  1056. begin
  1057. Result:=ValidatorKeywords;
  1058. end;
  1059. procedure TJSONSchemaValidations.Assign(Source: TPersistent);
  1060. var
  1061. aSource: TJSONSchemaValidations absolute Source;
  1062. begin
  1063. if Source is TJSONSchemaValidations then
  1064. begin
  1065. FKeywordData:=[];
  1066. UniqueItems:=aSource.UniqueItems;
  1067. Types:=aSource.Types;
  1068. Required:=aSource.Required;
  1069. Pattern:=aSource.Pattern;
  1070. MultipleOf:=aSource.MultipleOf;
  1071. MinProperties:=aSource.MinProperties;
  1072. MinLength:=aSource.MinLength;
  1073. MinItems:=aSource.MinItems;
  1074. Minimum:=aSource.Minimum;
  1075. MinContains:=aSource.MinContains;
  1076. MaxProperties:=aSource.MaxProperties;
  1077. MaxLength:=aSource.MaxLength;
  1078. MaxItems:=aSource.MaxItems;
  1079. Maximum:=aSource.Maximum;
  1080. MaxContains:=aSource.MaxContains;
  1081. Format:=aSource.Format;
  1082. ExclusiveMinimum:=aSource.ExclusiveMinimum;
  1083. ExclusiveMaximum:=aSource.ExclusiveMaximum;
  1084. contentMediaType:=aSource.contentMediaType;
  1085. contentEncoding:=aSource.contentEncoding;
  1086. constValue:=aSource.constValue.Clone;
  1087. enum:=aSource.Enum.Clone as TJSONArray;
  1088. end else
  1089. inherited Assign(Source);
  1090. end;
  1091. function TJsonSchema.CreateMetadata: TJSONSchemaMetadata;
  1092. begin
  1093. Result:=TJSONSchemaMetadata.Create(Self);
  1094. end;
  1095. function TJsonSchema.CreateValidations: TJsonSchemaValidations;
  1096. begin
  1097. Result:=TJsonSchemaValidations.Create(Self);
  1098. end;
  1099. procedure TJsonSchema.CheckConstrained;
  1100. begin
  1101. end;
  1102. function TJsonSchema.CreateChildSchema: TJsonSchema;
  1103. begin
  1104. Result:=TJsonSchemaClass(ClassType).Create(Self);
  1105. end;
  1106. function TJsonSchema.RootSchema: TJSONSchema;
  1107. begin
  1108. Result:=Self;
  1109. While Assigned(Result.Parent) do
  1110. Result:=Result.Parent;
  1111. end;
  1112. function TJsonSchema.GetNamedList(const aName : string) : TJSONSchemaList;
  1113. Function TestList(aList : TJSONSchemaList; out aRes : TJSONSchemaList) : Boolean;
  1114. begin
  1115. Result:=Assigned(aList) and (aList.Keyword<>jskUnknown) and (aName=aList.Keyword.AsString);
  1116. if Result then
  1117. aRes:=aList;
  1118. end;
  1119. begin
  1120. Result:=Nil;
  1121. If TestList(FPatternProperties,Result) then exit;
  1122. If TestList(FPrefixItems,Result) then exit;
  1123. If TestList(FProperties,Result) then exit;
  1124. If TestList(FItems,Result) then exit;
  1125. If TestList(FAllOf,Result) then exit;
  1126. If TestList(FAnyOf,Result) then exit;
  1127. If TestList(FOneOf,Result) then exit;
  1128. If TestList(FDependentSchemas,Result) then exit;
  1129. If TestList(FDefs,Result) then exit;
  1130. end;
  1131. function TJsonSchema.Find(const aPath: String): TJSONSchema;
  1132. var
  1133. P : Integer;
  1134. aSubPath,aName : string;
  1135. SchemaList : TJSONSchemaList;
  1136. begin
  1137. Result:=Nil;
  1138. aSubPath:='';
  1139. P:=Pos('/',aPath);
  1140. if P=0 then
  1141. aName:=aPath
  1142. else
  1143. begin
  1144. aName:=Copy(aPath,1,P-1);
  1145. aSubPath:=Copy(aPath,P+1);
  1146. end;
  1147. if aName='' then
  1148. Result:=Self
  1149. else if aName='#' then
  1150. Result:=RootSchema
  1151. else
  1152. begin
  1153. SchemaList:=GetNamedList(aName);
  1154. if Assigned(SchemaList) then
  1155. Exit(SchemaList.FindIDOrNames(aSubPath))
  1156. else
  1157. Result:=FindChild(aName);
  1158. end;
  1159. if Assigned(Result) and (aSubPath<>'') then
  1160. Result:=Result.Find(aSubPath);
  1161. end;
  1162. function TJsonSchema.IndexOfChild(const aName: String): Integer;
  1163. begin
  1164. Result:=FChildren.Count-1;
  1165. While (Result>=0) and (ChildSchemas[Result].Name<>aName) do
  1166. Dec(Result);
  1167. end;
  1168. function TJsonSchema.FindChild(const aName : String) : TJSONSchema;
  1169. var
  1170. Idx : integer;
  1171. begin
  1172. Idx:=IndexOfChild(aName);
  1173. if Idx=-1 then
  1174. Result:=nil
  1175. else
  1176. Result:=ChildSchemas[Idx];
  1177. end;
  1178. function TJsonSchema.GetPath: String;
  1179. begin
  1180. if Parent=Nil then
  1181. Result:='#'
  1182. else
  1183. Result:=Parent.Path+'/'+Name;
  1184. end;
  1185. { TJSONSchemaList }
  1186. function TJSONSchemaList.GetSchema(aIndex : integer): TJSONSchema;
  1187. begin
  1188. Result:=Items[aIndex] as TJSONSchema;
  1189. end;
  1190. procedure TJSONSchemaList.SetSchema(aIndex : integer; AValue: TJSONSchema);
  1191. begin
  1192. Items[aIndex]:=aValue;
  1193. end;
  1194. constructor TJSONSchemaList.Create(aOwner: TJSONSchema; aKeyWord: TJSONSchemaKeyword);
  1195. begin
  1196. Inherited Create(True);
  1197. FSchemaOwner:=aOwner;
  1198. FKeyword:=aKeyword;
  1199. end;
  1200. function TJSONSchemaList.FindIDOrNames(aPath: String): TJSONSchema;
  1201. var
  1202. I,P : Integer;
  1203. aSubPath,aName : string;
  1204. begin
  1205. Result:=Nil;
  1206. aSubPath:='';
  1207. P:=Pos('/',aPath);
  1208. if (P=0) then
  1209. aName:=aPath
  1210. else
  1211. begin
  1212. aName:=Copy(aPath,1,P-1);
  1213. aSubPath:=Copy(aPath,P+1);
  1214. end;
  1215. if aName='' then
  1216. exit;
  1217. I:=Count-1;
  1218. While (Result=Nil) and (I>=0) do
  1219. begin
  1220. Result:=Schemas[I];
  1221. if (Result.ID<>aName) and (Result.Name<>aName) then
  1222. Result:=Nil;
  1223. Dec(I);
  1224. end;
  1225. if Assigned(Result) and (aSubPath<>'') then
  1226. Result.Find(aSubPath);
  1227. end;
  1228. function TJSONSchemaList.Add(const aName: string): TJSONSchema;
  1229. begin
  1230. if FSchemaOwner=Nil then
  1231. Result:=TJSONSchema.Create
  1232. else
  1233. begin
  1234. Result:=SchemaOwner.CreateChildSchema(aName);
  1235. if Keyword<>jskUnknown then
  1236. SchemaOwner.SetKeyWordData(Keyword);
  1237. end;
  1238. Inherited Add(Result);
  1239. end;
  1240. function TJSONSchemaList.Add(Schema: TJSONSchema): Integer;
  1241. begin
  1242. Result:=Inherited Add(Schema);
  1243. if Keyword<>jskUnknown then
  1244. SchemaOwner.SetKeyWordData(Keyword);
  1245. end;
  1246. end.