Browse Source

* Refactor to use jsonwriter

Michaël Van Canneyt 9 months ago
parent
commit
4f10c539ba

+ 0 - 8
packages/fcl-jsonschema/src/fpjson.schema.consts.pp

@@ -146,14 +146,6 @@ Resourcestring
   SErrUnexpectedTypeNotInSet = 'Invalid JSON type at <<%s>>, expected one of: [%s], got: "%s"';
   SErrUnexpectedTypeNotInSet = 'Invalid JSON type at <<%s>>, expected one of: [%s], got: "%s"';
   SErrInvalidType = 'Invalid JSON type %s at <<%s>>';
   SErrInvalidType = 'Invalid JSON type %s at <<%s>>';
 
 
-  // Writer
-  SErrNoObjectsOnStack = 'No objects created on stack';
-  SPropertyNameAlreadySet = 'Cannot set property name to "%s", it is already set to "%s"';
-  SErrNotAtStructuredValue = 'Current value is not a structured value';
-  SErrCannotPop = 'Cannot pop, stack empty';
-  SErrNoPushOnSimpleValue = 'Cannot push on top of non-structured value';
-  SErrNoPropertyNameForPush = 'Cannot push to object without property name';
-
   // Validator
   // Validator
   SSchemaInfo = 'Schema info: "%s" : %s';
   SSchemaInfo = 'Schema info: "%s" : %s';
   SErrNoFalseMatch = '"false" schema does not match any JSON';
   SErrNoFalseMatch = '"false" schema does not match any JSON';

+ 115 - 490
packages/fcl-jsonschema/src/fpjson.schema.writer.pp

@@ -21,9 +21,9 @@ interface
 
 
 uses
 uses
   {$IFDEF FPC_DOTTEDUNITS}
   {$IFDEF FPC_DOTTEDUNITS}
-  System.Classes, System.SysUtils, FpJson.Data, FpJson.Schema.Types, FpJson.Schema.Schema;
+  System.Classes, System.SysUtils, FpJson.Data, FpJson.Schema.Types, FpJson.Schema.Schema, FpJson.Writer;
   {$ELSE}
   {$ELSE}
-  Classes, SysUtils, fpjson, FpJson.Schema.Types, FpJson.Schema.Schema;
+  Classes, SysUtils, fpjson, FpJson.Schema.Types, FpJson.Schema.Schema, jsonwriter;
   {$ENDIF}
   {$ENDIF}
 
 
 Type
 Type
@@ -33,97 +33,32 @@ Type
 
 
   TJSONSchemaWriter = class(TComponent)
   TJSONSchemaWriter = class(TComponent)
   private
   private
+    FWriter : TAbstractJSONWriter;
   Protected
   Protected
-    Procedure WriteProperty(const aName : TJSONStringType);
-    Procedure WriteProperty(const aName : TJSONStringType; aValue : Boolean);
-    Procedure WriteProperty(const aName : TJSONStringType; aValue : Integer);
-    Procedure WriteProperty(const aName : TJSONStringType; aValue : Int64);
-    Procedure WriteProperty(const aName : TJSONStringType; aValue : Double);
-    Procedure WriteProperty(const aName : TJSONStringType; aValue : String);
-    Procedure WriteProperty(const aName : TJSONStringType; aValue : TJSONSchema);
-    Procedure WriteProperty(const aName : TJSONStringType; aValue : TJSONSchemaList);
-    Procedure WriteProperty(const aName : TJSONStringType; aValue : TStrings);
-    Procedure WriteProperty(const aName : TJSONStringType; aValue : TJSONData);
     Procedure WriteProperty(const aName : TJSONStringType; aValue : TSchemaDependentRequiredList);
     Procedure WriteProperty(const aName : TJSONStringType; aValue : TSchemaDependentRequiredList);
     Procedure WriteProperty(const aName : TJSONStringType; aValue : TJSONSchemaVocabularyList);
     Procedure WriteProperty(const aName : TJSONStringType; aValue : TJSONSchemaVocabularyList);
     Procedure WriteProperty(const aName : TJSONStringType; aValue : TSchemaSimpleTypes);
     Procedure WriteProperty(const aName : TJSONStringType; aValue : TSchemaSimpleTypes);
-    procedure WriteValue(aValue: TJSONData);
-    procedure WriteValue(aValue: TStrings);
-    // Override in descendants
-    Procedure WriteValue(); virtual; abstract;
-    Procedure WriteValue(aValue : Boolean); virtual; abstract;
-    Procedure WriteValue(aValue : Integer); virtual; abstract;
-    Procedure WriteValue(aValue : Int64); virtual; abstract;
-    Procedure WriteValue(aValue : Double); virtual; abstract;
-    Procedure WriteValue(const aValue : String); virtual; abstract;
-    Procedure StartProperty(const aName: string); virtual; abstract;
-    Procedure EndProperty; virtual; abstract;
-    Procedure StartArray; virtual; abstract;
-    Procedure EndArray; virtual; abstract;
-    Procedure NextElement; virtual; abstract;
-    Procedure StartObject; virtual; abstract;
-    Procedure EndObject; virtual; abstract;
+    procedure WriteProperty(const aName: TJSONStringType; aValue: TJSONSchema);
+    procedure WriteProperty(const aName: TJSONStringType; aValue: TJSONSchemaList);
     Procedure DoWriteSchema(aSchema : TJSONSchema);
     Procedure DoWriteSchema(aSchema : TJSONSchema);
+  Public
+    Procedure Writeschema(aSchema : TJSONSchema; aWriter : TAbstractJSONWriter);
   end;
   end;
 
 
   { TJSONSchemaWriterJSON }
   { TJSONSchemaWriterJSON }
 
 
   TJSONSchemaWriterJSON = class(TJSONSchemaWriter)
   TJSONSchemaWriterJSON = class(TJSONSchemaWriter)
-  Private
-    FStack : Array of TJSONData;
-    FCount : Integer;
-    FPropertyName : String;
-  protected
-    function CurrentStruct : TJSONData;
-    Procedure PushData(Obj : TJSONData);
-    Procedure PopData;
-    procedure EndArray; override;
-    procedure EndObject; override;
-    procedure EndProperty; override;
-    procedure NextElement; override;
-    procedure StartArray; override;
-    procedure StartObject; override;
-    procedure StartProperty(const aName: string); override;
-    procedure WriteValue(aValue: Boolean); override;
-    procedure WriteValue(aValue: Double); override;
-    procedure WriteValue(aValue: Int64); override;
-    procedure WriteValue(aValue: Integer); override;
-    procedure WriteValue(const aValue: String); override;
-    procedure WriteValue; override;
   Public
   Public
-    function WriteSchema(aSchema : TJSONSchema) : TJSONData;
+    function WriteSchema(aSchema : TJSONSchema) : TJSONData; overload;
   end;
   end;
 
 
   { TJSONSchemaWriterStream }
   { TJSONSchemaWriterStream }
 
 
   TJSONSchemaWriterStream = class(TJSONSchemaWriter)
   TJSONSchemaWriterStream = class(TJSONSchemaWriter)
   private
   private
-    FStream: TStream;
-    FCounts : Array of Integer;
-    FLen : Integer;
     FStrictStrings: Boolean;
     FStrictStrings: Boolean;
-  Protected
-    Procedure PushElCount;
-    Procedure PopElCount;
-    Procedure IncElCount;
-    Function ElCount : Integer;
-    procedure WriteString(const aString : TJSONStringType);
-    Procedure WriteValue(); override;
-    Procedure WriteValue(aValue : Boolean); override;
-    Procedure WriteValue(aValue : Integer); override;
-    Procedure WriteValue(aValue : Int64); override;
-    Procedure WriteValue(aValue : Double); override;
-    Procedure WriteValue(const aValue : String); override;
-    Procedure StartProperty(const aName: string); override;
-    Procedure EndProperty; override;
-    Procedure StartArray; override;
-    Procedure EndArray; override;
-    Procedure NextElement; override;
-    Procedure StartObject; override;
-    Procedure EndObject; override;
-    Property Stream : TStream Read FStream;
   Public
   Public
-    procedure WriteSchema(aSchema : TJSONSchema; aStream : TStream);
+    procedure WriteSchema(aSchema : TJSONSchema; aStream : TStream); overload;
     property StrictStrings : Boolean Read FStrictStrings Write FStrictStrings;
     property StrictStrings : Boolean Read FStrictStrings Write FStrictStrings;
   end;
   end;
 
 
@@ -133,55 +68,15 @@ uses FpJson.Schema.Consts;
 
 
 { TJSONSchemaWriter }
 { TJSONSchemaWriter }
 
 
-procedure TJSONSchemaWriter.WriteProperty(const aName: TJSONStringType);
-begin
-  WriteValue(aName);
-end;
-
-procedure TJSONSchemaWriter.WriteProperty(const aName: TJSONStringType; aValue: Boolean);
-begin
-  StartProperty(aName);
-  WriteValue(aValue);
-  EndProperty;
-end;
-
-procedure TJSONSchemaWriter.WriteProperty(const aName: TJSONStringType; aValue: Integer);
-begin
-  StartProperty(aName);
-  WriteValue(aValue);
-  EndProperty;
-end;
-
-procedure TJSONSchemaWriter.WriteProperty(const aName: TJSONStringType; aValue: Int64);
-begin
-  StartProperty(aName);
-  WriteValue(aValue);
-  EndProperty;
-end;
-
-procedure TJSONSchemaWriter.WriteProperty(const aName: TJSONStringType; aValue: Double);
-begin
-  StartProperty(aName);
-  WriteValue(aValue);
-  EndProperty;
-end;
-
-procedure TJSONSchemaWriter.WriteProperty(const aName: TJSONStringType; aValue: String);
-begin
-  StartProperty(aName);
-  WriteValue(aValue);
-  EndProperty;
-end;
-
 procedure TJSONSchemaWriter.WriteProperty(const aName: TJSONStringType; aValue: TJSONSchema);
 procedure TJSONSchemaWriter.WriteProperty(const aName: TJSONStringType; aValue: TJSONSchema);
 begin
 begin
  case aValue.MatchType of
  case aValue.MatchType of
-   smNone,smAny : WriteProperty(aName,aValue.MatchType=smAny);
+   smNone,smAny : FWriter.WriteProperty(aName,aValue.MatchType=smAny);
  else
  else
    begin
    begin
-   StartProperty(aName);
+   FWriter.StartProperty(aName);
    DoWriteSchema(aValue);
    DoWriteSchema(aValue);
-   EndProperty;
+   FWriter.EndProperty;
    end;
    end;
  end;
  end;
 end;
 end;
@@ -192,84 +87,15 @@ var
   I : Integer;
   I : Integer;
 
 
 begin
 begin
-  StartProperty(aName);
-  StartArray;
+  FWriter.StartProperty(aName);
+  FWriter.StartArray;
   for I:=0 to aValue.Count-1 do
   for I:=0 to aValue.Count-1 do
     begin
     begin
-    NextElement;
+    FWriter.NextElement;
     DoWriteSchema(aValue.Schemas[i]);
     DoWriteSchema(aValue.Schemas[i]);
     end;
     end;
-  EndArray;
-  EndProperty;
-end;
-
-procedure TJSONSchemaWriter.WriteValue(aValue: TStrings);
-
-var
-  S : String;
-
-begin
-  StartArray;
-  For S in aValue do
-    begin
-    NextElement;
-    WriteValue(S);
-    end;
-  EndArray;
-end;
-
-procedure TJSONSchemaWriter.WriteProperty(const aName: TJSONStringType; aValue: TStrings);
-
-begin
-  StartProperty(aName);
-  WriteValue(aValue);
-  EndProperty;
-end;
-
-procedure TJSONSchemaWriter.WriteProperty(const aName: TJSONStringType; aValue: TJSONData);
-
-begin
-  StartProperty(aName);
-  WriteValue(aValue);
-  EndProperty();
-end;
-
-procedure TJSONSchemaWriter.WriteValue(aValue: TJSONData);
-
-var
-  Enum : TJSONEnum;
-
-begin
-  Case aValue.JSONType of
-    jtNull : WriteValue();
-    jtBoolean : WriteValue(aValue.AsBoolean);
-    jtString : WriteValue(aValue.AsString);
-    jtNumber :
-      case TJSONNumber(aValue).NumberType of
-       ntInteger : WriteValue(aValue.AsInteger);
-       ntInt64 : WriteValue(aValue.AsInt64);
-       ntFloat : WriteValue(aValue.AsFloat);
-       ntQword : WriteValue(aValue.AsInt64);
-      end;
-    jtObject :
-      begin
-      StartObject;
-      For Enum in aValue do
-        WriteProperty(Enum.Key,enum.Value);
-      EndObject;
-      end;
-    jtArray :
-      begin
-      StartArray;
-      For Enum in aValue do
-        begin
-        NextElement;
-        WriteValue(Enum.Value);
-        end;
-      EndArray;
-      end;
-  end;
-
+  FWriter.EndArray;
+  FWriter.EndProperty;
 end;
 end;
 
 
 procedure TJSONSchemaWriter.WriteProperty(const aName: TJSONStringType; aValue: TSchemaDependentRequiredList);
 procedure TJSONSchemaWriter.WriteProperty(const aName: TJSONStringType; aValue: TSchemaDependentRequiredList);
@@ -280,17 +106,20 @@ var
 begin
 begin
   if aValue.Count=0 then
   if aValue.Count=0 then
     exit;
     exit;
-  StartProperty(aName);
-  StartObject;
-  For I:=0 to aValue.Count-1 do
+  With FWriter do
     begin
     begin
-    D:=aValue[I];
-    StartProperty(D.Name);
-    WriteValue(D.Required);
+    StartProperty(aName);
+    StartObject;
+    For I:=0 to aValue.Count-1 do
+      begin
+      D:=aValue[I];
+      StartProperty(D.Name);
+      WriteValue(D.Required);
+      EndProperty;
+      end;
+    EndObject;
     EndProperty;
     EndProperty;
     end;
     end;
-  EndObject;
-  EndProperty;
 end;
 end;
 
 
 procedure TJSONSchemaWriter.WriteProperty(const aName: TJSONStringType; aValue: TJSONSchemaVocabularyList);
 procedure TJSONSchemaWriter.WriteProperty(const aName: TJSONStringType; aValue: TJSONSchemaVocabularyList);
@@ -302,17 +131,20 @@ var
 begin
 begin
   if aValue.Count=0 then
   if aValue.Count=0 then
     exit;
     exit;
-  StartProperty(aName);
-  StartObject;
-  For I:=0 to aValue.Count-1 do
+  With FWriter do
     begin
     begin
-    V:=aValue[I];
-    StartProperty(V.URL);
-    WriteValue(V.Enabled);
+    StartProperty(aName);
+    StartObject;
+    For I:=0 to aValue.Count-1 do
+      begin
+      V:=aValue[I];
+      StartProperty(V.URL);
+      WriteValue(V.Enabled);
+      EndProperty;
+      end;
+    EndObject;
     EndProperty;
     EndProperty;
     end;
     end;
-  EndObject;
-  EndProperty;
 end;
 end;
 
 
 procedure TJSONSchemaWriter.WriteProperty(const aName: TJSONStringType; aValue: TSchemaSimpleTypes);
 procedure TJSONSchemaWriter.WriteProperty(const aName: TJSONStringType; aValue: TSchemaSimpleTypes);
@@ -321,15 +153,18 @@ var
   St : TSchemaSimpleType;
   St : TSchemaSimpleType;
 
 
 begin
 begin
-  StartProperty(aName);
-  StartArray;
-  For ST in aValue do
+  With FWriter do
     begin
     begin
-    NextElement;
-    WriteValue(ST.AsString);
+    StartProperty(aName);
+    StartArray;
+    For ST in aValue do
+      begin
+      NextElement;
+      WriteValue(ST.AsString);
+      end;
+    EndArray;
+    EndProperty;
     end;
     end;
-  EndArray;
-  EndProperty;
 end;
 end;
 
 
 procedure TJSONSchemaWriter.DoWriteSchema(aSchema: TJSONSchema);
 procedure TJSONSchemaWriter.DoWriteSchema(aSchema: TJSONSchema);
@@ -337,45 +172,47 @@ procedure TJSONSchemaWriter.DoWriteSchema(aSchema: TJSONSchema);
 var
 var
   aKeyword : TJSONSchemaKeyword;
   aKeyword : TJSONSchemaKeyword;
   PropName : TJSONStringType;
   PropName : TJSONStringType;
+  W : TAbstractJSONWriter;
 
 
 begin
 begin
+  W:=FWriter;
   if (aSchema.MatchType in [smAny,smNone]) then
   if (aSchema.MatchType in [smAny,smNone]) then
-    WriteValue(aSchema.MatchType=smAny)
+    W.WriteValue(aSchema.MatchType=smAny)
   else
   else
     begin
     begin
-    StartObject;
+    W.StartObject;
     For aKeyword in TJSONSchemaKeyword do
     For aKeyword in TJSONSchemaKeyword do
       if aSchema.HasKeywordData(aKeyWord) then
       if aSchema.HasKeywordData(aKeyWord) then
         begin
         begin
         PropName:=aKeyword.AsString;
         PropName:=aKeyword.AsString;
         Case aKeyword of
         Case aKeyword of
         jskUnknown : ;
         jskUnknown : ;
-        jskId : WriteProperty(PropName,aSchema.ID);
-        jskAnchor : WriteProperty(PropName,aSchema.Anchor);
-        jskSchema : WriteProperty(PropName,aSchema.Schema);
+        jskId : W.WriteProperty(PropName,aSchema.ID);
+        jskAnchor : W.WriteProperty(PropName,aSchema.Anchor);
+        jskSchema : W.WriteProperty(PropName,aSchema.Schema);
         jskDefs : WriteProperty(PropName,aSchema.Defs);
         jskDefs : WriteProperty(PropName,aSchema.Defs);
-        jskTitle : WriteProperty(PropName,aSchema.Metadata.Title);
-        jskDescription : WriteProperty(PropName,aSchema.Metadata.Description);
-        jskDefault : WriteProperty(PropName,aSchema.MetaData.DefaultValue);
-        jskMultipleOf : WriteProperty(PropName,aSchema.Validations.MultipleOf);
-        jskMaximum : WriteProperty(PropName,aSchema.Validations.Maximum);
-        jskExclusiveMaximum : WriteProperty(PropName,aSchema.Validations.ExclusiveMaximum);
-        jskMinimum : WriteProperty(PropName,aSchema.Validations.Minimum);
-        jskExclusiveMinimum : WriteProperty(PropName,aSchema.Validations.ExclusiveMinimum);
-        jskMaxLength : WriteProperty(PropName,aSchema.Validations.MaxLength);
-        jskMinLength : WriteProperty(PropName,aSchema.Validations.MinLength);
-        jskPattern : WriteProperty(PropName,aSchema.Validations.Pattern);
+        jskTitle : W.WriteProperty(PropName,aSchema.Metadata.Title);
+        jskDescription : W.WriteProperty(PropName,aSchema.Metadata.Description);
+        jskDefault : W.WriteProperty(PropName,aSchema.MetaData.DefaultValue);
+        jskMultipleOf : W.WriteProperty(PropName,aSchema.Validations.MultipleOf);
+        jskMaximum : W.WriteProperty(PropName,aSchema.Validations.Maximum);
+        jskExclusiveMaximum : W.WriteProperty(PropName,aSchema.Validations.ExclusiveMaximum);
+        jskMinimum : W.WriteProperty(PropName,aSchema.Validations.Minimum);
+        jskExclusiveMinimum : W.WriteProperty(PropName,aSchema.Validations.ExclusiveMinimum);
+        jskMaxLength : W.WriteProperty(PropName,aSchema.Validations.MaxLength);
+        jskMinLength : W.WriteProperty(PropName,aSchema.Validations.MinLength);
+        jskPattern : W.WriteProperty(PropName,aSchema.Validations.Pattern);
         // jskAdditionalItems : WriteProperty(PropName,aSchema.Validations.AdditionalItems);
         // jskAdditionalItems : WriteProperty(PropName,aSchema.Validations.AdditionalItems);
         jskItems : WriteProperty(PropName,aSchema.Items);
         jskItems : WriteProperty(PropName,aSchema.Items);
         jskPrefixItems : WriteProperty(PropName,aSchema.PrefixItems);
         jskPrefixItems : WriteProperty(PropName,aSchema.PrefixItems);
-        jskMaxItems : WriteProperty(PropName,aSchema.Validations.MaxItems);
-        jskMinItems : WriteProperty(PropName,aSchema.Validations.MinItems);
-        jskUniqueItems : WriteProperty(PropName,aSchema.Validations.UniqueItems);
-        jskMaxProperties : WriteProperty(PropName,aSchema.Validations.MaxProperties);
-        jskMinProperties : WriteProperty(PropName,aSchema.Validations.MinProperties);
-        jskMaxContains : WriteProperty(PropName,aSchema.Validations.MaxContains);
-        jskMinContains : WriteProperty(PropName,aSchema.Validations.MinContains);
-        jskRequired : WriteProperty(PropName,aSchema.Validations.Required);
+        jskMaxItems : W.WriteProperty(PropName,aSchema.Validations.MaxItems);
+        jskMinItems : W.WriteProperty(PropName,aSchema.Validations.MinItems);
+        jskUniqueItems : W.WriteProperty(PropName,aSchema.Validations.UniqueItems);
+        jskMaxProperties : W.WriteProperty(PropName,aSchema.Validations.MaxProperties);
+        jskMinProperties : W.WriteProperty(PropName,aSchema.Validations.MinProperties);
+        jskMaxContains : W.WriteProperty(PropName,aSchema.Validations.MaxContains);
+        jskMinContains : W.WriteProperty(PropName,aSchema.Validations.MinContains);
+        jskRequired : W.WriteProperty(PropName,aSchema.Validations.Required);
         jskAdditionalProperties : WriteProperty(PropName,aSchema.AdditionalProperties);
         jskAdditionalProperties : WriteProperty(PropName,aSchema.AdditionalProperties);
         jskProperties : WriteProperty(PropName,aSchema.Properties);
         jskProperties : WriteProperty(PropName,aSchema.Properties);
         jskPatternProperties: WriteProperty(PropName,aSchema.PatternProperties);
         jskPatternProperties: WriteProperty(PropName,aSchema.PatternProperties);
@@ -383,293 +220,81 @@ begin
         jskDependentSchemas : WriteProperty(PropName,aSchema.DependentSchemas);
         jskDependentSchemas : WriteProperty(PropName,aSchema.DependentSchemas);
 
 
         jskDependentRequired : WriteProperty(PropName,aSchema.Validations.DependentRequired);
         jskDependentRequired : WriteProperty(PropName,aSchema.Validations.DependentRequired);
-        jskEnum: WriteProperty(PropName,aSchema.Validations.Enum);
+        jskEnum: W.WriteProperty(PropName,aSchema.Validations.Enum);
         jskType : WriteProperty(PropName,aSchema.Validations.Types);
         jskType : WriteProperty(PropName,aSchema.Validations.Types);
 
 
         jskAllOf : WriteProperty(PropName,aSchema.AllOf);
         jskAllOf : WriteProperty(PropName,aSchema.AllOf);
         jskAnyOf : WriteProperty(PropName,aSchema.AnyOf);
         jskAnyOf : WriteProperty(PropName,aSchema.AnyOf);
         jskOneOf : WriteProperty(PropName,aSchema.OneOf);
         jskOneOf : WriteProperty(PropName,aSchema.OneOf);
         jskNot : WriteProperty(PropName,aSchema.NotSchema);
         jskNot : WriteProperty(PropName,aSchema.NotSchema);
-        jskFormat  : WriteProperty(PropName,aSchema.Validations.Format);
-        jskRef : WriteProperty(PropName,aSchema.Ref);
+        jskFormat  : W.WriteProperty(PropName,aSchema.Validations.Format);
+        jskRef : W.WriteProperty(PropName,aSchema.Ref);
         jskIf : WriteProperty(PropName,aSchema.IfSchema);
         jskIf : WriteProperty(PropName,aSchema.IfSchema);
         jskElse : WriteProperty(PropName,aSchema.ElseSchema);
         jskElse : WriteProperty(PropName,aSchema.ElseSchema);
         jskThen : WriteProperty(PropName,aSchema.ThenSchema);
         jskThen : WriteProperty(PropName,aSchema.ThenSchema);
-        jskDynamicRef : WriteProperty(PropName,aSchema.DynamicRef);
-        jskDynamicAnchor : WriteProperty(PropName,aSchema.DynamicAnchor);
+        jskDynamicRef : W.WriteProperty(PropName,aSchema.DynamicRef);
+        jskDynamicAnchor : W.WriteProperty(PropName,aSchema.DynamicAnchor);
         jskContains : WriteProperty(PropName,aSchema.Contains);
         jskContains : WriteProperty(PropName,aSchema.Contains);
-        jskComment : WriteProperty(PropName,aSchema.Comment);
-        jskConst : WriteProperty(PropName,aSchema.Validations.constValue);
+        jskComment : W.WriteProperty(PropName,aSchema.Comment);
+        jskConst : W.WriteProperty(PropName,aSchema.Validations.constValue);
         jskUnevaluatedItems : WriteProperty(PropName,aSchema.UnevaluatedItems);
         jskUnevaluatedItems : WriteProperty(PropName,aSchema.UnevaluatedItems);
         jskUnevaluatedProperties : WriteProperty(PropName,aSchema.UnevaluatedProperties);
         jskUnevaluatedProperties : WriteProperty(PropName,aSchema.UnevaluatedProperties);
-        jskContentEncoding : WriteProperty(PropName,aSchema.Validations.contentEncoding);
-        jskContentMediaType : WriteProperty(PropName,aSchema.Validations.contentMediaType);
+        jskContentEncoding : W.WriteProperty(PropName,aSchema.Validations.contentEncoding);
+        jskContentMediaType : W.WriteProperty(PropName,aSchema.Validations.contentMediaType);
         jskContentSchema : WriteProperty(PropName,aSchema.Validations.contentSchema);
         jskContentSchema : WriteProperty(PropName,aSchema.Validations.contentSchema);
-        jskExamples : WriteProperty(PropName,aSchema.Metadata.Examples);
-        jskDeprecated : WriteProperty(PropName,aSchema.Metadata.Deprecated);
-        jskReadOnly : WriteProperty(PropName,aSchema.Metadata.ReadOnly);
-        jskWriteOnly : WriteProperty(PropName,aSchema.Metadata.WriteOnly);
+        jskExamples : W.WriteProperty(PropName,aSchema.Metadata.Examples);
+        jskDeprecated : W.WriteProperty(PropName,aSchema.Metadata.Deprecated);
+        jskReadOnly : W.WriteProperty(PropName,aSchema.Metadata.ReadOnly);
+        jskWriteOnly : W.WriteProperty(PropName,aSchema.Metadata.WriteOnly);
         jskVocabulary : WriteProperty(PropName,aSchema.Vocabulary);
         jskVocabulary : WriteProperty(PropName,aSchema.Vocabulary);
         end;
         end;
         end;
         end;
-    EndObject;
-    end;
-end;
-
-{ TJSONSchemaWriterJSON }
-
-function TJSONSchemaWriterJSON.CurrentStruct: TJSONData;
-begin
-  Result:=Nil;
-  if FCount>0 then
-    begin
-    Result:=FStack[FCount-1];
-    if not (Result.JSONType in StructuredJSONTypes) then
-      Result:=Nil;
+    W.EndObject;
     end;
     end;
 end;
 end;
 
 
-procedure TJSONSchemaWriterJSON.PushData(Obj: TJSONData);
-
-var
-  D : TJSONData;
-  O : TJSONObject absolute D;
-  A : TJSONArray absolute D;
-  AddToStack : Boolean;
-
-begin
-  AddToStack:=(Obj.JSONType in StructuredJSONTypes) or (FCount=0);
-  D:=CurrentStruct;
-  if (D=Nil) then
-    begin
-    if (FCount>0) then
-      Raise EJSONSchemaWriter.Create(SErrNoPushOnSimpleValue);
-    end
-  else
-    Case D.JSONType of
-    jtObject:
-      begin
-      if FPropertyName = '' then
-        Raise EJSONSchemaWriter.Create(SErrNoPropertyNameForPush);
-      O.Add(FPropertyName,Obj);
-      FPropertyName:='';
-      end;
-    jtArray:
-      begin
-      A.Add(Obj);
-      FPropertyName:='';
-      end;
-    end;
-  if AddToStack then
-    begin
-    if FCount=Length(FStack) then
-      SetLength(FStack,FCount+10);
-    FStack[FCount]:=Obj;
-    Inc(FCount);
-    end;
-end;
-
-procedure TJSONSchemaWriterJSON.PopData;
-begin
- if FCount=0 then
-   Raise EJSONSchemaWriter.Create(SErrCannotPop);
- Dec(FCount);
-end;
-
-procedure TJSONSchemaWriterJSON.EndArray;
-begin
-  PopData;
-end;
-
-procedure TJSONSchemaWriterJSON.EndObject;
+procedure TJSONSchemaWriter.Writeschema(aSchema: TJSONSchema; aWriter: TAbstractJSONWriter);
 begin
 begin
-  PopData;
-end;
-
-procedure TJSONSchemaWriterJSON.EndProperty;
-begin
-  If CurrentStruct=Nil then
-    Raise EJSONSchemaWriter.Create(SErrNotAtStructuredValue);
-end;
-
-procedure TJSONSchemaWriterJSON.NextElement;
-begin
-  If CurrentStruct=Nil then
-    Raise EJSONSchemaWriter.Create(SErrNotAtStructuredValue);
-end;
-
-procedure TJSONSchemaWriterJSON.StartArray;
-begin
-  PushData(TJSONArray.Create);
-end;
-
-procedure TJSONSchemaWriterJSON.StartObject;
-begin
-  PushData(TJSONObject.Create);
-end;
-
-procedure TJSONSchemaWriterJSON.StartProperty(const aName: string);
-begin
-  if FPropertyName<>'' then
-    Raise EJSONSchemaWriter.CreateFmt(SPropertyNameAlreadySet,[aName,FPropertyName]);
-  FPropertyName:=aName;
-end;
-
-procedure TJSONSchemaWriterJSON.WriteValue(aValue: Boolean);
-begin
-  PushData(TJSONBoolean.Create(aValue));
-end;
-
-procedure TJSONSchemaWriterJSON.WriteValue(aValue: Double);
-begin
-  PushData(TJSONFloatNumber.Create(aValue));
-end;
-
-procedure TJSONSchemaWriterJSON.WriteValue(aValue: Int64);
-begin
-  PushData(TJSONInt64Number.Create(aValue));
+  FWriter:=aWriter;
+  try
+    DoWriteSchema(aSchema);
+  finally
+    FWriter:=Nil;
+  end;
 end;
 end;
 
 
-procedure TJSONSchemaWriterJSON.WriteValue(aValue: Integer);
-begin
-  PushData(TJSONIntegerNumber.Create(aValue));
-end;
+{ TJSONSchemaWriterJSON }
 
 
-procedure TJSONSchemaWriterJSON.WriteValue(const aValue: String);
-begin
-  PushData(TJSONString.Create(aValue));
-end;
+function TJSONSchemaWriterJSON.WriteSchema(aSchema: TJSONSchema): TJSONData;
 
 
-procedure TJSONSchemaWriterJSON.WriteValue;
-begin
-  PushData(TJSONNull.Create);
-end;
+var
+  lWriter : TJSONDataWriter;
 
 
-function TJSONSchemaWriterJSON.WriteSchema(aSchema: TJSONSchema): TJSONData;
 begin
 begin
-  DoWriteSchema(aSchema);
-  if (Length(FStack)=0) or Not Assigned(FStack[0]) then
-    Raise EJSONSchemaWriter.Create(SErrNoObjectsOnStack);
-  Result:=FStack[0];
+  lWriter:=TJSONDataWriter.Create;
+  try
+    WriteSchema(aSchema,lWriter);
+    Result:=lWriter.ExtractData;
+  finally
+    lWriter.Free;
+  end;
 end;
 end;
 
 
 { TJSONSchemaWriterStream }
 { TJSONSchemaWriterStream }
 
 
 procedure TJSONSchemaWriterStream.WriteSchema(aSchema: TJSONSchema; aStream: TStream);
 procedure TJSONSchemaWriterStream.WriteSchema(aSchema: TJSONSchema; aStream: TStream);
-begin
-  FStream:=aStream;
-  DoWriteSchema(aSchema);
-end;
-
-procedure TJSONSchemaWriterStream.PushElCount;
-begin
-  if FLen=Length(FCounts) then
-    SetLength(FCounts,FLen+10);
-  FCounts[FLen]:=0;
-  Inc(Flen);
-end;
-
-procedure TJSONSchemaWriterStream.PopElCount;
-begin
-  if FLen>0 then
-    Dec(FLen);
-end;
-
-procedure TJSONSchemaWriterStream.IncElCount;
-begin
-  if Flen>0 then
-    Inc(FCounts[FLen-1]);
-end;
-
-function TJSONSchemaWriterStream.ElCount: Integer;
-begin
-  Result:=FCounts[FLen-1];
-end;
-
-procedure TJSONSchemaWriterStream.WriteString(const aString: TJSONStringType);
-begin
-  if Length(aString)>0 then
-    FStream.WriteBuffer(aString[1],Length(aString))
-end;
-
-procedure TJSONSchemaWriterStream.WriteValue();
-begin
-  WriteString('null');
-end;
-
-procedure TJSONSchemaWriterStream.WriteValue(aValue: Boolean);
-begin
-  WriteString(BoolToStr(aValue,'true','false'));
-end;
-
-procedure TJSONSchemaWriterStream.WriteValue(aValue: Integer);
-begin
-  WriteString(IntToStr(aValue));
-end;
-
-procedure TJSONSchemaWriterStream.WriteValue(aValue: Int64);
-begin
-  WriteString(IntToStr(aValue));
-end;
-
-procedure TJSONSchemaWriterStream.WriteValue(aValue: Double);
 
 
 var
 var
-  s : String;
-begin
-  Str(aValue,s);
-  WriteString(S);
-end;
-
-procedure TJSONSchemaWriterStream.WriteValue(const aValue: String);
+  lWriter : TJSONStreamWriter;
 
 
 begin
 begin
-  WriteString('"'+StringToJSONString(aValue,StrictStrings)+'"');
-end;
-
-procedure TJSONSchemaWriterStream.StartProperty(const aName: string);
-begin
-  if ElCount>0 then
-    NextElement;
-  WriteString('"'+StringToJSONString(aName,StrictStrings)+'":');
-  IncElCount;
-end;
-
-procedure TJSONSchemaWriterStream.EndProperty;
-begin
-  // Nothing
-end;
-
-procedure TJSONSchemaWriterStream.StartArray;
-begin
-  WriteString('[');
-  PushElCount;
-end;
-
-procedure TJSONSchemaWriterStream.EndArray;
-begin
-  PopElCount;
-  WriteString(']');
-end;
-
-procedure TJSONSchemaWriterStream.NextElement;
-begin
-  if ElCount>0 then
-    WriteString(',');
-  IncElCount;
-end;
-
-
-procedure TJSONSchemaWriterStream.StartObject;
-begin
-  WriteString('{');
-  PushElCount;
-end;
-
-procedure TJSONSchemaWriterStream.EndObject;
-begin
-  WriteString('}');
-  PopElCount;
+  lWriter:=TJSONStreamWriter.Create(aStream);
+  try
+    lWriter.StrictStrings:=StrictStrings;
+    WriteSchema(aSchema,lWriter);
+  finally
+    LWriter.Free;
+  end;
 end;
 end;
 
 
 end.
 end.