json.monkey2 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. Namespace std.json
  2. #rem monkeydoc JsonError class.
  3. #end
  4. Class JsonError Extends Exception
  5. End
  6. #rem monkeydoc JsonValue class.
  7. This is base class of all JsonValue types.
  8. #end
  9. Class JsonValue Abstract
  10. Method ToBool:Bool() Virtual
  11. Assert( False )
  12. Return Null
  13. End
  14. Method ToNumber:Double() Virtual
  15. Assert( False )
  16. Return Null
  17. End
  18. Method ToString:String() Virtual
  19. Assert( False )
  20. Return Null
  21. End
  22. Method ToArray:Stack<JsonValue>() Virtual
  23. Assert( False )
  24. Return Null
  25. End
  26. Method ToObject:StringMap<JsonValue>() Virtual
  27. Assert( False )
  28. Return Null
  29. End
  30. Method ToJson:String() Virtual
  31. Local buf:=New StringStack
  32. PushJson( buf )
  33. Return buf.Join( "" )
  34. End
  35. Method ToInt:Int()
  36. Return Int( ToNumber() )
  37. End
  38. Method ToLong:Long()
  39. Return Long( ToNumber() )
  40. End
  41. Method ToFloat:Float()
  42. Return Float( ToNumber() )
  43. End
  44. Method ToDouble:Double()
  45. Return ToNumber()
  46. End
  47. Method Save:Bool( path:String )
  48. Local buf:=New StringStack
  49. PushJson( buf )
  50. Local src:=buf.Join( "" )
  51. Return stringio.SaveString( src,path )
  52. End
  53. Function Load:JsonValue( path:String )
  54. Local src:=stringio.LoadString( path )
  55. If Not src Return Null
  56. Local parser:=New JsonParser( src )
  57. Local value:=parser.ParseValue()
  58. Return value
  59. End
  60. Protected
  61. #rem monkeydoc @hidden
  62. #end
  63. Method PushJson:Void( buf:StringStack ) Virtual
  64. buf.Push( ToJson() )
  65. End
  66. End
  67. #rem monkeydoc JsonBool class.
  68. #end
  69. Class JsonBool Extends JsonValue
  70. Const TrueValue:JsonBool=New JsonBool( True )
  71. Const FalseValue:JsonBool=New JsonBool( False )
  72. Method New( data:Bool=False )
  73. _data=data
  74. End
  75. Property Data:Bool()
  76. Return _data
  77. Setter( data:Bool )
  78. _data=data
  79. End
  80. Method ToBool:Bool() Override
  81. Return _data
  82. End
  83. Method ToNumber:Double() Override
  84. Return _data
  85. End
  86. Method ToString:String() Override
  87. Return _data ? "true" Else "false"
  88. End
  89. Method ToJson:String() Override
  90. Return _data ? "true" Else "false"
  91. End
  92. Private
  93. Field _data:Bool
  94. End
  95. #rem monkeydoc JsonNumber class.
  96. #end
  97. Class JsonNumber Extends JsonValue
  98. Method New( data:Double=0 )
  99. _data=data
  100. End
  101. Property Data:Double()
  102. Return _data
  103. Setter( data:Double )
  104. _data=data
  105. End
  106. Method ToBool:Bool() Override
  107. Return _data
  108. End
  109. Method ToNumber:Double() Override
  110. Return _data
  111. End
  112. Method ToString:String() Override
  113. Return _data
  114. End
  115. Method ToJson:String() Override
  116. Return _data
  117. End
  118. Private
  119. Field _data:Double
  120. End
  121. #rem monkeydoc JsonString class.
  122. #end
  123. Class JsonString Extends JsonValue
  124. Method New( data:String="" )
  125. _data=data
  126. End
  127. Property Data:String()
  128. Return _data
  129. Setter( data:String )
  130. _data=data
  131. End
  132. Method ToBool:Bool() Override
  133. Return _data
  134. End
  135. Method ToNumber:Double() Override
  136. Return Double( _data )
  137. End
  138. Method ToString:String() Override
  139. Return _data
  140. End
  141. Method ToJson:String() Override
  142. Return "~q"+_data.Replace( "~q","\~q" )+"~q"
  143. End
  144. Private
  145. Field _data:String
  146. End
  147. #rem monkeydoc JsonArray class.
  148. #end
  149. Class JsonArray Extends JsonValue
  150. Method New( length:Int=0 )
  151. _data=New Stack<JsonValue>( length )
  152. End
  153. Method New( data:JsonValue[] )
  154. _data=New Stack<JsonValue>( data )
  155. End
  156. Method New( data:Stack<JsonValue> )
  157. _data=data
  158. End
  159. Property Data:Stack<JsonValue>()
  160. Return _data
  161. Setter( data:Stack<JsonValue> )
  162. _data=data
  163. End
  164. Property Length:Int()
  165. Return _data.Length
  166. End
  167. Method Add( value:JsonValue )
  168. _data.Add( value )
  169. End
  170. Method ToArray:Stack<JsonValue>() Override
  171. Return _data
  172. End
  173. Private
  174. Field _data:Stack<JsonValue>
  175. Method PushJson:Void( buf:StringStack ) Override
  176. buf.Push( "[" )
  177. Local t:=False
  178. For Local value:=Eachin _data
  179. If t buf.Push( "," )
  180. If value value.PushJson( buf ) Else buf.Push( "null" )
  181. t=True
  182. Next
  183. buf.Push( "]" )
  184. End
  185. End
  186. #rem monkeydoc JsonObject class.
  187. #end
  188. Class JsonObject Extends JsonValue
  189. Method New( data:StringMap<JsonValue> =Null )
  190. If Not data data=New StringMap<JsonValue>
  191. _data=data
  192. End
  193. Property Data:StringMap<JsonValue>()
  194. Return _data
  195. Setter( data:StringMap<JsonValue> )
  196. _data=data
  197. End
  198. Method Contains:Bool( key:String )
  199. Return _data.Contains( key )
  200. End
  201. Operator[]:JsonValue( key:String )
  202. Return _data[key]
  203. End
  204. Operator[]=( key:String,value:JsonValue )
  205. _data[key]=value
  206. End
  207. Method ToObject:StringMap<JsonValue>() Override
  208. Return Data
  209. End
  210. Function Load:JsonObject( path:String )
  211. Return Cast<JsonObject>( JsonValue.Load( path ) )
  212. End
  213. Private
  214. Field _data:StringMap<JsonValue>
  215. Method PushJson:Void( buf:StringStack ) Override
  216. buf.Push( "{" )
  217. Local t:=False
  218. For Local it:=Eachin _data
  219. If t buf.Push( "," )
  220. buf.Push( "~q"+it.Key.Replace( "~q","\~q" )+"~q:" )
  221. If it.Value it.Value.PushJson( buf ) Else buf.Push( "null" )
  222. t=True
  223. Next
  224. buf.Push( "}" )
  225. End
  226. End
  227. #rem monkeydoc JsonParser class.
  228. #end
  229. Class JsonParser
  230. Method New( json:String )
  231. _text=json
  232. Bump()
  233. End
  234. Method ParseValue:JsonValue()
  235. If TokeType=T_STRING Return New JsonString( ParseString() )
  236. If TokeType=T_NUMBER Return New JsonNumber( ParseNumber() )
  237. If Toke="{" Return New JsonObject( ParseObject() )
  238. If Toke="[" Return New JsonArray( ParseArray() )
  239. If CParse( "true" ) Return JsonBool.TrueValue
  240. If CParse( "false" ) Return JsonBool.FalseValue
  241. If CParse( "null" ) Return Null
  242. Return Null
  243. End
  244. Private
  245. Const T_EOF:=0
  246. Const T_STRING:=1
  247. Const T_NUMBER:=2
  248. Const T_SYMBOL:=3
  249. Const T_IDENT:=4
  250. Field _text:String
  251. Field _toke:String
  252. Field _type:Int
  253. Field _pos:Int
  254. Method GetChar:Int()
  255. If _pos=_text.Length Throw New JsonError()
  256. _pos+=1
  257. Return _text[_pos-1]
  258. End
  259. Method PeekChar:Int()
  260. If _pos=_text.Length Return 0
  261. Return _text[_pos]
  262. End
  263. Method ParseChar:Void( chr:Int )
  264. If _pos>=_text.Length Or _text[_pos]<>chr Throw New JsonError()
  265. _pos+=1
  266. End
  267. Method CParseChar:Bool( chr:Int )
  268. If _pos>=_text.Length Or _text[_pos]<>chr Return False
  269. _pos+=1
  270. Return True
  271. End
  272. Method CParseDigits:Bool()
  273. Local p:=_pos
  274. While _pos<_text.Length And _text[_pos]>=48 And _text[_pos]<=57
  275. _pos+=1
  276. Wend
  277. Return _pos>p
  278. End
  279. Method Bump:String()
  280. While _pos<_text.Length And _text[_pos]<=32
  281. _pos+=1
  282. Wend
  283. If _pos=_text.Length
  284. _toke=""
  285. _type=T_EOF
  286. Return _toke
  287. Endif
  288. Local pos:=_pos
  289. Local chr:=GetChar()
  290. If chr=34
  291. Repeat
  292. Local chr:=GetChar()
  293. If chr=34 Exit
  294. If chr=92 GetChar()
  295. Forever
  296. _type=T_STRING
  297. Else If chr=39
  298. Repeat
  299. Local chr:=GetChar()
  300. If chr=39 Exit
  301. If chr=92 GetChar()
  302. Forever
  303. _type=T_STRING
  304. Else If (chr>=48 And chr<=57) Or chr=45
  305. If chr=45 '-
  306. chr=GetChar()
  307. If chr<48 Or chr>57 Throw New JsonError()
  308. Endif
  309. If chr<>48 '0
  310. CParseDigits()
  311. End
  312. If CParseChar( 46 ) '.
  313. CParseDigits()
  314. Endif
  315. If CParseChar( 69 ) Or CParseChar( 101 ) 'e E
  316. If PeekChar()=43 Or PeekChar()=45 GetChar() '+ -
  317. If Not CParseDigits() Throw New JsonError()
  318. Endif
  319. _type=T_NUMBER
  320. Else If (chr>=65 And chr<91) Or (chr>=97 And chr<123) Or chr=95
  321. chr=PeekChar()
  322. While (chr>=65 And chr<91) Or (chr>=97 And chr<123) Or (chr>=48 And chr<58) Or chr=95
  323. GetChar()
  324. chr=PeekChar()
  325. Wend
  326. _type=T_IDENT
  327. Else
  328. _type=T_SYMBOL
  329. Endif
  330. _toke=_text.Slice( pos,_pos )
  331. Return _toke
  332. End
  333. Property Toke:String()
  334. Return _toke
  335. End
  336. Property TokeType:Int()
  337. Return _type
  338. End
  339. Method CParse:Bool( toke:String )
  340. If toke<>_toke Return False
  341. Bump()
  342. Return True
  343. End
  344. Method Parse:Void( toke:String )
  345. If Not CParse( toke ) Throw New JsonError()
  346. End
  347. Method ParseObject:StringMap<JsonValue>()
  348. Parse( "{" )
  349. Local map:=New StringMap<JsonValue>
  350. If CParse( "}" ) Return map
  351. Repeat
  352. Local name:=Toke
  353. If TokeType=T_IDENT
  354. Bump()
  355. Else
  356. name=ParseString()
  357. Endif
  358. Parse( ":" )
  359. Local value:=ParseValue()
  360. map.Set( name,value )
  361. Until Not CParse( "," )
  362. Parse( "}" )
  363. Return map
  364. End
  365. Method ParseArray:Stack<JsonValue>()
  366. Parse( "[" )
  367. Local stack:=New Stack<JsonValue>
  368. If CParse( "]" ) Return stack
  369. Repeat
  370. Local value:=ParseValue()
  371. stack.Add( value )
  372. Until Not CParse( "," )
  373. Parse( "]" )
  374. Return stack
  375. End
  376. Method ParseString:String()
  377. If TokeType<>T_STRING Throw New JsonError()
  378. Local toke:=Toke.Slice( 1,-1 )
  379. Local i:=toke.Find( "\" )
  380. If i<>-1
  381. Local frags:=New StringStack,p:=0,esc:=""
  382. Repeat
  383. If i+1>=toke.Length Throw New JsonError()
  384. frags.Push( toke.Slice( p,i ) )
  385. Select toke[i+1]
  386. Case 34 esc="~q" '\"
  387. Case 92 esc="\" '\\
  388. Case 47 esc="/" '\/
  389. Case 98 esc=String.FromChar( 8 ) '\b
  390. Case 102 esc=String.FromChar( 12 ) '\f
  391. Case 114 esc=String.FromChar( 13 ) '\r
  392. Case 110 esc=String.FromChar( 10 ) '\n
  393. Case 117 '\uxxxx
  394. If i+6>toke.Length Throw New JsonError()
  395. Local val:=0
  396. For Local j:=2 Until 6
  397. Local chr:=toke[i+j]
  398. If chr>=48 And chr<58
  399. val=val Shl 4 | (chr-48)
  400. Else If chr>=65 And chr<123
  401. chr&=31
  402. If chr<1 Or chr>6 Throw New JsonError()
  403. val=val Shl 4 | (chr+9)
  404. Else
  405. Throw New JsonError()
  406. Endif
  407. Next
  408. esc=String.FromChar( val )
  409. i+=4
  410. Default
  411. Throw New JsonError()
  412. End
  413. frags.Push( esc )
  414. p=i+2
  415. i=toke.Find( "\",p )
  416. If i<>-1 Continue
  417. frags.Push( toke.Slice( p ) )
  418. Exit
  419. Forever
  420. toke=frags.Join( "" )
  421. Endif
  422. Bump()
  423. Return toke
  424. End
  425. Method ParseNumber:Double()
  426. If TokeType<>T_NUMBER Throw New JsonError()
  427. Local toke:=Toke
  428. Bump()
  429. Return Double( toke )
  430. End
  431. End