jsonparser.pp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. {
  2. This file is part of the Free Component Library
  3. JSON source parser
  4. Copyright (c) 2007 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. {$mode objfpc}
  12. {$h+}
  13. unit jsonparser;
  14. interface
  15. uses
  16. Classes, SysUtils, fpJSON, jsonscanner, jsonreader;
  17. Type
  18. { TJSONParser }
  19. TJSONParser = Class(TBaseJSONReader)
  20. private
  21. FStack : Array of TJSONData;
  22. FStackPos : integer;
  23. FStruct : TJSONData;
  24. FValue : TJSONData;
  25. FKey: TJSONStringType;
  26. procedure Pop(aType: TJSONType);
  27. Procedure Push(AValue : TJSONData);
  28. Function NewValue(AValue : TJSONData) : TJSONData;
  29. Protected
  30. Procedure KeyValue(Const AKey : TJSONStringType); override;
  31. Procedure StringValue(Const AValue : TJSONStringType);override;
  32. Procedure NullValue; override;
  33. Procedure FloatValue(Const AValue : Double); override;
  34. Procedure BooleanValue(Const AValue : Boolean); override;
  35. Procedure NumberValue(Const AValue : TJSONStringType); override;
  36. Procedure IntegerValue(Const AValue : integer); override;
  37. Procedure Int64Value(Const AValue : int64); override;
  38. Procedure QWordValue(Const AValue : QWord); override;
  39. Procedure StartArray; override;
  40. Procedure StartObject; override;
  41. Procedure EndArray; override;
  42. Procedure EndObject; override;
  43. Public
  44. function Parse: TJSONData;
  45. end;
  46. EJSONParser = jsonReader.EJSONParser;
  47. implementation
  48. Resourcestring
  49. SErrStructure = 'Structural error';
  50. { TJSONParser }
  51. procedure DefJSONParserHandler(AStream: TStream; const AUseUTF8: Boolean; out
  52. Data: TJSONData);
  53. Var
  54. P : TJSONParser;
  55. AOptions: TJSONOptions;
  56. begin
  57. Data:=Nil;
  58. AOptions:=[];
  59. if AUseUTF8 then
  60. Include(AOptions,joUTF8);
  61. P:=TJSONParser.Create(AStream,AOptions);
  62. try
  63. Data:=P.Parse;
  64. finally
  65. P.Free;
  66. end;
  67. end;
  68. procedure TJSONParser.Pop(aType: TJSONType);
  69. begin
  70. if (FStackPos=0) then
  71. DoError(SErrStructure);
  72. If (FStruct.JSONType<>aType) then
  73. DoError(SErrStructure);
  74. Dec(FStackPos);
  75. FStruct:=FStack[FStackPos];
  76. end;
  77. procedure TJSONParser.Push(AValue: TJSONData);
  78. begin
  79. if (FStackPos=Length(FStack)) then
  80. SetLength(FStack,FStackPos+10);
  81. FStack[FStackPos]:=FStruct;
  82. Inc(FStackPos);
  83. FStruct:=AValue;
  84. end;
  85. function TJSONParser.NewValue(AValue: TJSONData): TJSONData;
  86. begin
  87. Result:=AValue;
  88. // Add to existing structural type
  89. if (FStruct is TJSONObject) then
  90. begin
  91. TJSONObject(FStruct).Add(FKey,AValue);
  92. FKey:='';
  93. end
  94. else if (FStruct is TJSONArray) then
  95. TJSONArray(FStruct).Add(AValue);
  96. // The first actual value is our result
  97. if (FValue=Nil) then
  98. FValue:=AValue;
  99. end;
  100. procedure TJSONParser.KeyValue(const AKey: TJSONStringType);
  101. begin
  102. if (FStruct is TJSONObject) and (FKey='') then
  103. FKey:=Akey
  104. else
  105. DoError('Duplicatekey or no object');
  106. end;
  107. procedure TJSONParser.StringValue(const AValue: TJSONStringType);
  108. begin
  109. NewValue(CreateJSON(AValue));
  110. end;
  111. procedure TJSONParser.NullValue;
  112. begin
  113. NewValue(CreateJSON);
  114. end;
  115. procedure TJSONParser.FloatValue(const AValue: Double);
  116. begin
  117. NewValue(CreateJSON(AValue));
  118. end;
  119. procedure TJSONParser.BooleanValue(const AValue: Boolean);
  120. begin
  121. NewValue(CreateJSON(AValue));
  122. end;
  123. procedure TJSONParser.NumberValue(const AValue: TJSONStringType);
  124. begin
  125. // Do nothing
  126. if AValue='' then ;
  127. end;
  128. procedure TJSONParser.IntegerValue(const AValue: integer);
  129. begin
  130. NewValue(CreateJSON(AValue));
  131. end;
  132. procedure TJSONParser.Int64Value(const AValue: int64);
  133. begin
  134. NewValue(CreateJSON(AValue));
  135. end;
  136. procedure TJSONParser.QWordValue(const AValue: QWord);
  137. begin
  138. NewValue(CreateJSON(AValue));
  139. end;
  140. procedure TJSONParser.StartArray;
  141. begin
  142. Push(NewValue(CreateJSONArray([])))
  143. end;
  144. procedure TJSONParser.StartObject;
  145. begin
  146. Push(NewValue(CreateJSONObject([])));
  147. end;
  148. procedure TJSONParser.EndArray;
  149. begin
  150. Pop(jtArray);
  151. end;
  152. procedure TJSONParser.EndObject;
  153. begin
  154. Pop(jtObject);
  155. end;
  156. function TJSONParser.Parse: TJSONData;
  157. begin
  158. SetLength(FStack,0);
  159. FStackPos:=0;
  160. FValue:=Nil;
  161. FStruct:=Nil;
  162. try
  163. DoExecute;
  164. Result:=FValue;
  165. except
  166. On E : exception do
  167. begin
  168. FreeAndNil(FValue);
  169. FStackPos:=0;
  170. SetLength(FStack,0);
  171. Raise;
  172. end;
  173. end;
  174. end;
  175. {
  176. Consume next token and convert to JSON data structure.
  177. If AtCurrent is true, the current token is used. If false,
  178. a token is gotten from the scanner.
  179. If AllowEOF is false, encountering a tkEOF will result in an exception.
  180. }
  181. Procedure InitJSONHandler;
  182. begin
  183. if GetJSONParserHandler=Nil then
  184. SetJSONParserHandler(@DefJSONParserHandler);
  185. end;
  186. Procedure DoneJSONHandler;
  187. begin
  188. if GetJSONParserHandler=@DefJSONParserHandler then
  189. SetJSONParserHandler(Nil);
  190. end;
  191. initialization
  192. InitJSONHandler;
  193. finalization
  194. DoneJSONHandler;
  195. end.