json.monkey2 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158
  1. #rem monkeydoc
  2. JSON (JavaScript Object Notation) is a lightweight data-interchange format.
  3. \## Reading JSON data
  4. Use the [[JsonObject.Load]] function to load JSON data from a file, or [[JsonObject.Parse]] to parse JSON data from a string.
  5. \## Writing JSON data
  6. To save a JSON object, use the [[JsonObject.Save]] function.
  7. #end
  8. Namespace std.json
  9. #rem monkeydoc JsonError class.
  10. #end
  11. Class JsonError Extends Throwable
  12. End
  13. #rem monkeydoc JsonValue class.
  14. This is base class of all JsonValue types.
  15. #end
  16. Class JsonValue
  17. Const NullValue:=New JsonValue
  18. #rem monkeydoc True if value is null.
  19. #end
  20. Property IsNull:Bool()
  21. Return Self=NullValue
  22. End
  23. #rem monkeydoc True if value is a bool.
  24. #end
  25. Property IsBool:Bool() Virtual
  26. Return False
  27. End
  28. #rem monkeydoc True if value is a number.
  29. #end
  30. Property IsNumber:Bool() Virtual
  31. Return False
  32. End
  33. #rem monkeydoc True if value is a string.
  34. #end
  35. Property IsString:Bool() Virtual
  36. Return False
  37. End
  38. #rem monkeydoc True if value is an array.
  39. #end
  40. Property IsArray:Bool() Virtual
  41. Return False
  42. End
  43. #rem monkeydoc True if value is an object.
  44. #end
  45. Property IsObject:Bool() Virtual
  46. Return False
  47. End
  48. #rem monkeydoc Gets bool value.
  49. If the value is a bool, returns its actual value.
  50. If the value is not a bool, false is returned by default.
  51. #end
  52. Method ToBool:Bool() Virtual
  53. Return False
  54. End
  55. #rem monkeydoc Gets number value.
  56. If the value is a number, returns its actual value.
  57. If the value is not a number, 0 is returned by default.
  58. #end
  59. Method ToNumber:Double() Virtual
  60. Return 0
  61. End
  62. #rem monkeydoc Gets string value.
  63. If the value is a string, returns its actual value.
  64. If the value is not a string, "" is returned by default.
  65. #end
  66. Method ToString:String() Virtual
  67. Return ""
  68. End
  69. #rem monkeydoc Gets array value.
  70. If the value is an array, returns its actual value in the form of a Stack<JsonValue> object.
  71. If the value is not an array, null is returned by default.
  72. #end
  73. Method ToArray:Stack<JsonValue>() Virtual
  74. Return Null
  75. End
  76. #rem monkeydoc Gets object value.
  77. If the value is an object, returns its actual value in the form of a StringMap<JsonValue> object.
  78. If the value is not an object, null is returned by default.
  79. #end
  80. Method ToObject:StringMap<JsonValue>() Virtual
  81. Return Null
  82. End
  83. #rem monkeydoc Converts the value to a JSON string.
  84. #end
  85. Method ToJson:String() Virtual
  86. Local buf:=New StringStack
  87. PushJson( buf )
  88. Return buf.Join( "" )
  89. End
  90. #rem monkeydoc Saves the value as a JSON string to a file.
  91. #end
  92. Method Save:Bool( path:String )
  93. Local buf:=New StringStack
  94. PushJson( buf )
  95. Local src:=buf.Join( "" )
  96. Return stringio.SaveString( src,path )
  97. End
  98. #rem monkeydoc Load the value from a JSON string stored in a file.
  99. #end
  100. Function Load:JsonValue( path:String,throwex:Bool=False )
  101. Local src:=stringio.LoadString( path )
  102. If Not src Return Null
  103. Return Parse( src,throwex )
  104. End
  105. #rem monkeydoc Creates a JSONValue from a JSON string.
  106. Returns null if the json could not be parsed.
  107. #end
  108. Function Parse:JsonValue( src:String,throwex:Bool=False )
  109. Try
  110. Local parser:=New JsonParser( src )
  111. Return parser.ParseValue()
  112. Catch ex:JsonError
  113. If throwex Throw ex
  114. End
  115. Return Null
  116. End
  117. Protected
  118. Global _indent:String
  119. #rem monkeydoc @hidden
  120. #end
  121. Method New()
  122. End
  123. #rem monkeydoc @hidden
  124. #end
  125. Method PushJson:Void( buf:StringStack ) Virtual
  126. buf.Push( ToJson() )
  127. End
  128. End
  129. #rem monkeydoc JsonBool class.
  130. #end
  131. Class JsonBool Extends JsonValue
  132. Const TrueValue:JsonBool=New JsonBool( True )
  133. Const FalseValue:JsonBool=New JsonBool( False )
  134. Method New( data:Bool=False )
  135. _data=data
  136. End
  137. #rem monkeydoc @hidden Deprecated!
  138. #end
  139. Property Data:Bool()
  140. Return _data
  141. Setter( data:Bool )
  142. _data=data
  143. End
  144. Property IsBool:Bool() Override
  145. Return True
  146. End
  147. Method ToBool:Bool() Override
  148. Return _data
  149. End
  150. #rem monkeydoc @hidden Deprecated!
  151. #end
  152. Method ToNumber:Double() Override
  153. Return _data
  154. End
  155. #rem monkeydoc @hidden Deprecated!
  156. #end
  157. Method ToString:String() Override
  158. Return _data ? "true" Else "false"
  159. End
  160. Method ToJson:String() Override
  161. If _data Return "true"
  162. Return "false"
  163. End
  164. Private
  165. Field _data:Bool
  166. End
  167. #rem monkeydoc JsonNumber class.
  168. #end
  169. Class JsonNumber Extends JsonValue
  170. Method New( data:Double=0 )
  171. _data=data
  172. End
  173. #rem monkeydoc @hidden Deprecated!
  174. #end
  175. Property Data:Double()
  176. Return _data
  177. Setter( data:Double )
  178. _data=data
  179. End
  180. Property IsNumber:Bool() Override
  181. Return True
  182. End
  183. Method ToNumber:Double() Override
  184. Return _data
  185. End
  186. #rem monkeydoc @hidden Deprecated!
  187. #end
  188. Method ToBool:Bool() Override
  189. Return _data
  190. End
  191. #rem monkeydoc @hidden Deprecated!
  192. #end
  193. Method ToString:String() Override
  194. Return _data
  195. End
  196. Method ToJson:String() Override
  197. Return String( _data )
  198. End
  199. Private
  200. Field _data:Double
  201. End
  202. #rem monkeydoc JsonString class.
  203. #end
  204. Class JsonString Extends JsonValue
  205. Method New( data:String="" )
  206. _data=data
  207. End
  208. #rem monkeydoc @hidden Deprecated!
  209. #end
  210. Property Data:String()
  211. Return _data
  212. Setter( data:String )
  213. _data=data
  214. End
  215. Property IsString:Bool() Override
  216. Return True
  217. End
  218. Method ToString:String() Override
  219. Return _data
  220. End
  221. #rem monkeydoc @hidden Deprecated!
  222. #end
  223. Method ToBool:Bool() Override
  224. Return _data
  225. End
  226. #rem monkeydoc @hidden Deprecated!
  227. #end
  228. Method ToNumber:Double() Override
  229. Return Double( _data )
  230. End
  231. Method ToJson:String() Override
  232. Return "~q"+_data.Replace( "~q","\~q" )+"~q"
  233. End
  234. Private
  235. Field _data:String
  236. End
  237. #rem monkeydoc JsonArray class.
  238. #end
  239. Class JsonArray Extends JsonValue
  240. Method New( length:Int=0 )
  241. _data=New Stack<JsonValue>( length )
  242. End
  243. Method New( data:JsonValue[] )
  244. _data=New Stack<JsonValue>( data )
  245. End
  246. Method New( data:Stack<JsonValue> )
  247. _data=data
  248. End
  249. #rem monkeydoc @hidden Deprecated!
  250. #end
  251. Property Data:Stack<JsonValue>()
  252. Return _data
  253. Setter( data:Stack<JsonValue> )
  254. _data=data
  255. End
  256. #rem monkeydoc Returns true.
  257. #end
  258. Property IsArray:Bool() Override
  259. Return True
  260. End
  261. #rem monkeydoc Gets the internal stack used to store the array.
  262. #end
  263. Method ToArray:Stack<JsonValue>() Override
  264. Return _data
  265. End
  266. #rem monkeydoc Gets an array element.
  267. Returns the json value at `index`.
  268. @param index Array index.
  269. #end
  270. Method GetValue:JsonValue( index:int )
  271. Assert( index>=0 And index<_data.Length )
  272. Return _data[index]
  273. End
  274. #rem monkeydoc Gets a bool array element.
  275. Returns the bool value at `index`, or false if `index` is out of range or the value at `index` is not a bool.
  276. @param index Array index.
  277. #end
  278. Method GetBool:Bool( index:int )
  279. Local value:=GetValue( index )
  280. If value Return value.ToBool()
  281. Return False
  282. End
  283. #rem monkeydoc Gets a numeric array element.
  284. Returns the numeric value at `index`, or 0 if `index` is out of range or the value at `index` is not numeric.
  285. @param index Array index.
  286. #end
  287. Method GetNumber:Double( index:int )
  288. Local value:=GetValue( index )
  289. If value Return value.ToNumber()
  290. Return 0
  291. End
  292. #rem monkeydoc Gets a string array element.
  293. Returns the string value at `index`, or an empty string if `index` is out of range or the value at `index` is not a string.
  294. @param index Array index.
  295. #end
  296. Method GetString:String( index:Int )
  297. Local value:=GetValue( index )
  298. If value Return value.ToString()
  299. Return ""
  300. End
  301. #rem monkeydoc Gets an array array element.
  302. Returns the array at `index`, or null if `index` is out of range or the value at `index` is not an array.
  303. @param index Array index.
  304. #end
  305. Method GetArray:JsonArray( index:int )
  306. Return Cast<JsonArray>( GetValue( index ) )
  307. End
  308. #rem monkeydoc Gets an object array element.
  309. Returns the object at `index`, or null if `index` is out of range or the value at `index` is not an object.
  310. @param index Array index.
  311. #end
  312. Method GetObject:JsonObject( index:Int )
  313. Return Cast<JsonObject>( GetValue( index ) )
  314. End
  315. #rem monkeydoc Sets an array element.
  316. Sets the json value at `index` to `value`.
  317. @param index Array index.
  318. @param value Value to set.
  319. #end
  320. Method SetValue( index:Int,value:JsonValue )
  321. Assert( index>=0 And index<_data.Length )
  322. _data[index]=value
  323. End
  324. #rem monkeydoc Sets an array element.
  325. Sets the json value at `index` to `value`.
  326. @param index Array index.
  327. @param value Value to set.
  328. #end
  329. Method SetBool( index:Int,value:Bool )
  330. SetValue( index,value ? JsonBool.TrueValue Else JsonBool.FalseValue )
  331. End
  332. #rem monkeydoc Sets an array element.
  333. Sets the json value at `index` to `value`.
  334. @param index Array index.
  335. @param value Value to set.
  336. #end
  337. Method SetNumber( index:int,value:Double )
  338. SetValue( index,New JsonNumber( value ) )
  339. End
  340. #rem monkeydoc Sets an array element.
  341. Sets the json value at `index` to `value`.
  342. @param index Array index.
  343. @param value Value to set.
  344. #end
  345. Method SetString( index:Int,value:String )
  346. SetValue( index,New JsonString( value ) )
  347. End
  348. #rem monkeydoc Sets an array element.
  349. Sets the json value at `index` to `value`.
  350. @param index Array index.
  351. @param value Value to set.
  352. #end
  353. Method SetArray( index:int,value:JsonValue[] )
  354. SetValue( index,New JsonArray( value ) )
  355. End
  356. Method SetArray( index:int,value:Stack<JsonValue> )
  357. SetValue( index,New JsonArray( value ) )
  358. End
  359. #rem monkeydoc Sets an array element.
  360. Sets the json value at `index` to `value`.
  361. @param index Array index.
  362. @param value Value to set.
  363. #end
  364. Method SetObject( index:Int,value:StringMap<JsonValue> )
  365. SetValue( index,New JsonObject( value ) )
  366. End
  367. #rem monkeydoc True if array is empty.
  368. #end
  369. Property Empty:Bool()
  370. Return _data.Empty
  371. End
  372. #rem monkeydoc Length of the array.
  373. #end
  374. Property Length:Int()
  375. Return _data.Length
  376. End
  377. #rem monkeydoc Gets the json value at an index.
  378. Returns the json value at `index`, or null if `index` is out of range.
  379. @param index The index.
  380. @return The json value at `index`.
  381. #end
  382. Operator[]:JsonValue( index:Int )
  383. If index<0 Or index>=_data.Length Return null
  384. Return _data[index]
  385. End
  386. #rem monkeydoc Sets the json value at an index.
  387. Sets the json value at `index` to `value`, or does nothing if `index` is out of range.
  388. @param index The index.
  389. @param value The json value to store at `index`.
  390. #end
  391. Operator[]=( index:Int,value:JsonValue )
  392. If index<0 Or index>=_data.Length Return
  393. DebugAssert( index>=0 )
  394. If index>=_data.Length _data.Resize( index+1 )
  395. _data[index]=value
  396. End
  397. #rem monkeydoc Gets an iterator to all json values in the array.
  398. #end
  399. Method All:Stack<JsonValue>.Iterator()
  400. Return _data.All()
  401. End
  402. #rem monkeydoc Adds a json value to the array.
  403. @param value The json value to add.
  404. #end
  405. Method Push( value:JsonValue )
  406. _data.Push( value )
  407. End
  408. #rem monkeydoc @hidden
  409. #end
  410. Method Add( value:JsonValue )
  411. _data.Add( value )
  412. End
  413. Private
  414. Field _data:Stack<JsonValue>
  415. Method PushJson:Void( buf:StringStack ) Override
  416. buf.Push( "[" )
  417. Local indent:=_indent
  418. Local n:=0
  419. For Local value:=Eachin _data
  420. If n
  421. buf.Push( "," )
  422. Endif
  423. n+=1
  424. If value
  425. buf.Push( value.ToJson() )
  426. Else
  427. buf.Push( "null" )
  428. Endif
  429. Next
  430. _indent=indent
  431. buf.Push( "]" )
  432. End
  433. End
  434. #rem monkeydoc JsonObject class.
  435. #end
  436. Class JsonObject Extends JsonValue
  437. Method New( data:StringMap<JsonValue> =Null )
  438. If Not data data=New StringMap<JsonValue>
  439. _data=data
  440. End
  441. #rem monkeydoc @hidden Deprecated!
  442. #end
  443. Property Data:StringMap<JsonValue>()
  444. Return _data
  445. Setter( data:StringMap<JsonValue> )
  446. _data=data
  447. End
  448. #rem monkeydoc Returns True.
  449. #end
  450. Property IsObject:Bool() Override
  451. Return True
  452. End
  453. #rem monkeydoc Gets the internal string map used to store the object.
  454. #end
  455. Method ToObject:StringMap<JsonValue>() Override
  456. Return _data
  457. End
  458. #rem monkeydoc Gets the value associated with a key.
  459. Returns the json value associated with `key`, or null if `key` does not exist.
  460. @param index Object key.
  461. #end
  462. Method GetValue:JsonValue( key:String )
  463. Return _data[key]
  464. End
  465. #rem monkeydoc Gets a bool from an object.
  466. Returns the bool value associated with `key`, or false if `key` does not exist or the value associated with `key` is not a bool.
  467. @param key Object key.
  468. #end
  469. Method GetBool:Bool( key:String )
  470. Local value:=GetValue( key )
  471. If value Return value.ToBool()
  472. Return False
  473. End
  474. #rem monkeydoc Gets a number from an object.
  475. Returns the numeric value associated with `key`, or 0 if `key` does not exist or the value associated with `key` is not numeric.
  476. @param key Object key.
  477. #end
  478. Method GetNumber:Double( key:String )
  479. Local value:=GetValue( key )
  480. If value Return value.ToNumber()
  481. Return 0
  482. End
  483. #rem monkeydoc Gets a string from an object.
  484. Returns the string value associated with `key`, or an empty string if `key` does not exist or the value associated with `key` is not a string.
  485. @param key Object key.
  486. #end
  487. Method GetString:String( key:String )
  488. Local value:=GetValue( key )
  489. If value Return value.ToString()
  490. Return ""
  491. End
  492. #rem monkeydoc Gets an array from an object.
  493. Returns the json array associated with `key`, or null if `key` does not exist or the value associated with `key` is not an array.
  494. @param key Object key.
  495. #end
  496. Method GetArray:JsonArray( key:String )
  497. Return Cast<JsonArray>( GetValue( key ) )
  498. End
  499. #rem monkeydoc Gets an object from the object.
  500. Returns the json object associated with `key`, or null if `key` does not exist or the value associated with `key` is not an object.
  501. @param key Object key.
  502. @return A json object.
  503. #end
  504. Method GetObject:JsonObject( key:String )
  505. Return Cast<JsonObject>( GetValue( key ) )
  506. End
  507. #rem monkeydoc Sets a key to a value.
  508. Sets the value associated with `key` in the object.
  509. Any previous value associated with `key` is overwritten.
  510. @param key Object key.
  511. @param value Value to set.
  512. #end
  513. Method SetValue( key:String,value:JsonValue )
  514. _data[key]=value
  515. End
  516. #rem monkeydoc Sets a key to a value.
  517. Sets the value associated with `key` in the object.
  518. Any previous value associated with `key` is overwritten.
  519. @param key Object key.
  520. @param value Value to set.
  521. #end
  522. Method SetBool( key:String,value:Bool )
  523. _data[key]=value ? JsonBool.TrueValue Else JsonBool.FalseValue
  524. End
  525. #rem monkeydoc Sets a key to a value.
  526. Sets the value associated with `key` in the object.
  527. Any previous value associated with `key` is overwritten.
  528. @param key Object key.
  529. @param value Value to set.
  530. #end
  531. Method SetNumber( key:String,value:Double )
  532. _data[key]=New JsonNumber( value )
  533. End
  534. #rem monkeydoc Sets a key to a value.
  535. Sets the value associated with `key` in the object.
  536. Any previous value associated with `key` is overwritten.
  537. @param key Object key.
  538. @param value Value to set.
  539. #end
  540. Method SetString( key:String,value:String )
  541. _data[key]=New JsonString( value )
  542. End
  543. #rem monkeydoc Sets a key to a value.
  544. Sets the value associated with `key` in the object.
  545. Any previous value associated with `key` is overwritten.
  546. @param key Object key.
  547. @param value Value to set.
  548. #end
  549. Method SetArray( key:String,value:JsonValue[] )
  550. _data[key]=New JsonArray( value )
  551. End
  552. Method SetArray( key:String,value:Stack<JsonValue> )
  553. _data[key]=New JsonArray( value )
  554. End
  555. #rem monkeydoc Sets a key to a value.
  556. Sets the value associated with `key` in the object.
  557. Any previous value associated with `key` is overwritten.
  558. @param key Object key.
  559. @param value Value to set.
  560. #end
  561. Method SetObject( key:String,value:StringMap<JsonValue> )
  562. _data[key]=New JsonObject( value )
  563. End
  564. #rem monkeydoc True if object is empty.
  565. #end
  566. Property Empty:Bool()
  567. Return _data.Empty
  568. End
  569. #rem monkeydoc Counts the number of keys in the object.
  570. Returns the number of keys contained in the object.
  571. @return The number of keys.
  572. #end
  573. Method Count:Int()
  574. Return _data.Count()
  575. End
  576. #rem monkeydoc Checks if the object contains a key.
  577. Returns true if object contains `key`.
  578. @param key Key to check for.
  579. @return True if object contains `key`.
  580. #end
  581. Method Contains:Bool( key:String )
  582. Return _data.Contains( key )
  583. End
  584. #rem monkeydoc Gets an iterator to all json values in the object.
  585. #end
  586. Method All:StringMap<JsonValue>.Iterator()
  587. Return _data.All()
  588. End
  589. #rem monkeydoc Gets the json value associated with a key.
  590. Returns the json value associated with `key`, or null if `key` does not exist.
  591. @param key The key.
  592. @return The json value associated with `key`.
  593. #end
  594. Operator[]:JsonValue( key:String )
  595. Return _data[key]
  596. End
  597. #rem monkeydoc Sets the json value in the object.
  598. Sets the json value associated with `key` to `value`.
  599. @param key The key.
  600. @param value The json value to associate with `key`.
  601. #end
  602. Operator[]=( key:String,value:JsonValue )
  603. _data[key]=value
  604. End
  605. Function Load:JsonObject( path:String,throwex:Bool=False )
  606. Local src:=std.stringio.LoadString( path )
  607. If Not src Return Null
  608. Return Parse( src,throwex )
  609. End
  610. Function Parse:JsonObject( json:String,throwex:Bool=False )
  611. Try
  612. Local parser:=New JsonParser( json )
  613. Return New JsonObject( parser.ParseObject() )
  614. Catch ex:JsonError
  615. If throwex Throw ex
  616. End
  617. Return Null
  618. End
  619. Private
  620. Field _data:StringMap<JsonValue>
  621. Method PushJson:Void( buf:StringStack ) Override
  622. buf.Push( "{~n" )
  623. _indent+="~t"
  624. Local t:=False
  625. For Local it:=Eachin _data
  626. If t buf.Push( ",~n" )
  627. buf.Push( _indent+"~q"+it.Key.Replace( "~q","\~q" )+"~q:" )
  628. If it.Value
  629. buf.Push( it.Value.ToJson() )
  630. Else
  631. buf.Push( "null" )
  632. Endif
  633. t=True
  634. Next
  635. _indent=_indent.Slice( 0,-1 )
  636. buf.Push( "~n"+_indent+"}" )
  637. End
  638. End
  639. #rem monkeydoc JsonParser class.
  640. #end
  641. Class JsonParser
  642. Method New( json:String )
  643. _text=json
  644. Bump()
  645. End
  646. Method ParseValue:JsonValue()
  647. If TokeType=T_STRING Return New JsonString( ParseString() )
  648. If TokeType=T_NUMBER Return New JsonNumber( ParseNumber() )
  649. If Toke="{" Return New JsonObject( ParseObject() )
  650. If Toke="[" Return New JsonArray( ParseArray() )
  651. If CParse( "true" ) Return JsonBool.TrueValue
  652. If CParse( "false" ) Return JsonBool.FalseValue
  653. If CParse( "null" ) Return JsonValue.NullValue
  654. Return Null
  655. End
  656. Private
  657. Const T_EOF:=0
  658. Const T_STRING:=1
  659. Const T_NUMBER:=2
  660. Const T_SYMBOL:=3
  661. Const T_IDENT:=4
  662. Field _text:String
  663. Field _toke:String
  664. Field _type:Int
  665. Field _pos:Int
  666. Method GetChar:Int()
  667. If _pos=_text.Length Throw New JsonError()
  668. _pos+=1
  669. Return _text[_pos-1]
  670. End
  671. Method PeekChar:Int()
  672. If _pos=_text.Length Return 0
  673. Return _text[_pos]
  674. End
  675. Method ParseChar:Void( chr:Int )
  676. If _pos>=_text.Length Or _text[_pos]<>chr Throw New JsonError()
  677. _pos+=1
  678. End
  679. Method CParseChar:Bool( chr:Int )
  680. If _pos>=_text.Length Or _text[_pos]<>chr Return False
  681. _pos+=1
  682. Return True
  683. End
  684. Method CParseDigits:Bool()
  685. Local p:=_pos
  686. While _pos<_text.Length And _text[_pos]>=48 And _text[_pos]<=57
  687. _pos+=1
  688. Wend
  689. Return _pos>p
  690. End
  691. Method Bump:String()
  692. While _pos<_text.Length
  693. If _text[_pos]=47
  694. '// comment? - can't live without 'em!
  695. If _pos+1=_text.Length Or _text[_pos+1]<>47 Exit
  696. _pos+=2
  697. While _pos<_text.Length And _text[_pos]<>10
  698. _pos+=1
  699. Wend
  700. If _pos<_text.Length _pos+=1
  701. Else
  702. If _text[_pos]>32 Exit
  703. _pos+=1
  704. Endif
  705. Wend
  706. If _pos=_text.Length
  707. _toke=""
  708. _type=T_EOF
  709. Return _toke
  710. Endif
  711. Local pos:=_pos
  712. Local chr:=GetChar()
  713. If chr=34
  714. Repeat
  715. Local chr:=GetChar()
  716. If chr=34 Exit
  717. If chr=92 GetChar()
  718. Forever
  719. _type=T_STRING
  720. Else If chr=39
  721. Repeat
  722. Local chr:=GetChar()
  723. If chr=39 Exit
  724. If chr=92 GetChar()
  725. Forever
  726. _type=T_STRING
  727. Else If (chr>=48 And chr<=57) Or chr=45
  728. If chr=45 '-
  729. chr=GetChar()
  730. If chr<48 Or chr>57 Throw New JsonError()
  731. Endif
  732. If chr<>48 '0
  733. CParseDigits()
  734. End
  735. If CParseChar( 46 ) '.
  736. CParseDigits()
  737. Endif
  738. If CParseChar( 69 ) Or CParseChar( 101 ) 'e E
  739. If PeekChar()=43 Or PeekChar()=45 GetChar() '+ -
  740. If Not CParseDigits() Throw New JsonError()
  741. Endif
  742. _type=T_NUMBER
  743. Else If (chr>=65 And chr<91) Or (chr>=97 And chr<123) Or chr=95
  744. chr=PeekChar()
  745. While (chr>=65 And chr<91) Or (chr>=97 And chr<123) Or (chr>=48 And chr<58) Or chr=95
  746. GetChar()
  747. chr=PeekChar()
  748. Wend
  749. _type=T_IDENT
  750. Else
  751. _type=T_SYMBOL
  752. Endif
  753. _toke=_text.Slice( pos,_pos )
  754. Return _toke
  755. End
  756. Property Toke:String()
  757. Return _toke
  758. End
  759. Property TokeType:Int()
  760. Return _type
  761. End
  762. Method CParse:Bool( toke:String )
  763. If toke<>_toke Return False
  764. Bump()
  765. Return True
  766. End
  767. Method Parse:Void( toke:String )
  768. If Not CParse( toke ) Throw New JsonError()
  769. End
  770. Method ParseObject:StringMap<JsonValue>()
  771. Parse( "{" )
  772. Local map:=New StringMap<JsonValue>
  773. If CParse( "}" ) Return map
  774. Repeat
  775. Local name:=Toke
  776. If TokeType=T_IDENT
  777. Bump()
  778. Else
  779. name=ParseString()
  780. Endif
  781. Parse( ":" )
  782. Local value:=ParseValue()
  783. map.Set( name,value )
  784. Until Not CParse( "," )
  785. Parse( "}" )
  786. Return map
  787. End
  788. Method ParseArray:Stack<JsonValue>()
  789. Parse( "[" )
  790. Local stack:=New Stack<JsonValue>
  791. If CParse( "]" ) Return stack
  792. Repeat
  793. Local value:=ParseValue()
  794. stack.Add( value )
  795. Until Not CParse( "," )
  796. Parse( "]" )
  797. Return stack
  798. End
  799. Method ParseString:String()
  800. If TokeType<>T_STRING Throw New JsonError()
  801. Local toke:=Toke.Slice( 1,-1 )
  802. Local i:=toke.Find( "\" )
  803. If i<>-1
  804. Local frags:=New StringStack,p:=0,esc:=""
  805. Repeat
  806. If i+1>=toke.Length Throw New JsonError()
  807. frags.Push( toke.Slice( p,i ) )
  808. Select toke[i+1]
  809. Case 34 esc="~q" '\"
  810. Case 92 esc="\" '\\
  811. Case 47 esc="/" '\/
  812. Case 98 esc=String.FromChar( 8 ) '\b
  813. Case 102 esc=String.FromChar( 12 ) '\f
  814. Case 114 esc=String.FromChar( 13 ) '\r
  815. Case 110 esc=String.FromChar( 10 ) '\n
  816. Case 117 '\uxxxx
  817. If i+6>toke.Length Throw New JsonError()
  818. Local val:=0
  819. For Local j:=2 Until 6
  820. Local chr:=toke[i+j]
  821. If chr>=48 And chr<58
  822. val=val Shl 4 | (chr-48)
  823. Else If chr>=65 And chr<123
  824. chr&=31
  825. If chr<1 Or chr>6 Throw New JsonError()
  826. val=val Shl 4 | (chr+9)
  827. Else
  828. Throw New JsonError()
  829. Endif
  830. Next
  831. esc=String.FromChar( val )
  832. i+=4
  833. Default
  834. Throw New JsonError()
  835. End
  836. frags.Push( esc )
  837. p=i+2
  838. i=toke.Find( "\",p )
  839. If i<>-1 Continue
  840. frags.Push( toke.Slice( p ) )
  841. Exit
  842. Forever
  843. toke=frags.Join( "" )
  844. Endif
  845. Bump()
  846. Return toke
  847. End
  848. Method ParseNumber:Double()
  849. If TokeType<>T_NUMBER Throw New JsonError()
  850. Local toke:=Toke
  851. Bump()
  852. Return Double( toke )
  853. End
  854. End