我电脑中收集的,也不知是哪位大侠的作品,不知对你有用否?
*
* VFP_Json.prg
*
function json_encode(xExpr) if vartype(_json)<>'O' public _json _json = newobject('json') endif
return _json.encode(@xExpr)
function json_decode(cJson)
local retval if vartype(_json)<>'O' public _json _json = newobject('json') endif retval = _json.decode(cJson) if not empty(_json.cError) return null endif
return retval
function json_getErrorMsg()
return _json.cError
function recordToJson
local nRecno,i,oObj, cRetVal if alias()=='' return '' endif oObj = newObject('myObj') for i=1 to fcount() oObj.set(Field(i),eval(Field(i))) next cRetVal = json_encode(oObj) if not empty(json_getErrorMsg()) cRetVal = 'ERROR:'+json_getErrorMsg() endif
return cRetVal
function tableToJson
local nRecno,i,oObj, cRetVal,nRec if alias()=='' return '' endif nRecno = recno() nRec = 1 dimension aInfo[1] scan oObj = newObject('myObj') for i=1 to fcount() oObj.set(Field(i),eval(Field(i))) next dimension aInfo[nRec] aInfo[nRec] = oObj nRec = nRec+1 endscan goto nRecno cRetVal = json_encode(@aInfo) if not empty(json_getErrorMsg()) cRetVal = 'ERROR:'+json_getErrorMsg() endif
return cRetVal
define class json as custom nPos=0 nLen=0 cJson='' cError=''
function encode(xExpr) local cTipo if type('ALen(xExpr)')=='N' cTipo = 'A' Else cTipo = VarType(xExpr) Endif Do Case Case cTipo=='D' return '"'+dtos(xExpr)+'"' Case cTipo=='N' return Transform(xExpr) Case cTipo=='L' return iif(xExpr,'true','false') Case cTipo=='X' return 'null' Case cTipo=='C' xExpr = allt(xExpr) xExpr = StrTran(xExpr, '\', '\\' ) xExpr = StrTran(xExpr, '/', '\/' ) xExpr = StrTran(xExpr, Chr(9),'\t' ) xExpr = StrTran(xExpr, Chr(10), '\n' ) xExpr = StrTran(xExpr, Chr(13), '\r' ) xExpr = StrTran(xExpr, '"', '\"' ) return '"'+xExpr+'"'
case cTipo=='O' local cProp, cJsonValue, cRetVal, aProp[1] =AMembers(aProp,xExpr) cRetVal = '' for each cProp in aProp if type('xExpr.'+cProp)=='U' or cProp=='CLASS' loop endif if type( 'ALen(xExpr.'+cProp+')' ) == 'N' Local i,nTotElem cJsonValue = '' nTotElem = Eval('ALen(xExpr.'+cProp+')') For i=1 to nTotElem cmd = 'cJsonValue=cJsonValue+","+ this.encode( xExpr.'+cProp+'[i])' &cmd. Next cJsonValue = '[' + substr(cJsonValue,2) + ']' else cJsonValue = this.encode( evaluate( 'xExpr.'+cProp ) ) endif if left(cProp,1)=='_' cProp = substr(cProp,2) endif cRetVal = cRetVal + ',' + '"' + lower(cProp) + '":' + cJsonValue next return '{' + substr(cRetVal,2) + '}'
case cTipo=='A' local valor, cRetVal cRetVal = '' for each valor in xExpr cRetVal = cRetVal + ',' +this.encode( valor ) next return'[' + substr(cRetVal,2) + ']' endcase
return ''
function decode(cJson) local retValue cJson = StrTran(cJson,chr(9),'') cJson = StrTran(cJson,chr(10),'') cJson = StrTran(cJson,chr(13),'') cJson = this.fixUnicode(cJson) this.nPos= 1 this.cJson = cJson this.nLen= len(cJson) this.cError = '' retValue = this.parsevalue() if not empty(this.cError) return null endif if this.getToken()<>null this.setError('Junk at the end of JSON input') return null endif return retValue function parseValue() local token token = this.getToken() if token==null this.setError('Nothing to parse') return null endif do case case token=='"' return this.parseString() case isdigit(token) or token=='-' return this.parseNumber() case token=='n' return this.expectedKeyword('null',null) case token=='f' return this.expectedKeyword('false',.f.) case token=='t' return this.expectedKeyword('true',.t.) case token=='{' return this.parseObject() case token=='[' return this.parseArray() otherwise this.setError('Unexpected token') endcase return function expectedKeyword(cWord,eValue) for i=1 to len(cWord) cChar = this.getChar() if cChar <> substr(cWord,i,1) this.setError("Expected keyword '" + cWord + "'") return '' endif this.nPos = this.nPos + 1 next return eValue
function parseObject() local retval, cPropName, xValue retval = createObject('myObj') this.nPos = this.nPos + 1 if this.getToken()<>'}' do while .t. cPropName = this.parseString() if not empty(this.cError) return null endif if this.getToken()<>':' this.setError("Expected ':' when parsing object") return null endif this.nPos = this.nPos + 1 xValue = this.parseValue() if not empty(this.cError) return null endif retval.set(cPropName, xValue) if this.getToken()<>',' exit endif this.nPos = this.nPos + 1 enddo endif if this.getToken()<>'}' this.setError("Expected '}' at the end of object") return null endif this.nPos = this.nPos + 1 return retval
function parseArray() local retVal, xValue retval = createObject('MyArray') this.nPos = this.nPos + 1 if this.getToken() <> ']' do while .t. xValue = this.parseValue() if not empty(this.cError) return null endif retval.add( xValue ) if this.getToken()<>',' exit endif this.nPos = this.nPos + 1 enddo if this.getToken() <> ']' this.setError('Expected ] at the end of array') return null endif endif this.nPos = this.nPos + 1 return retval
function parseString() local cRetVal, c if this.getToken()<>'"' this.setError('Expected "') return '' endif this.nPos = this.nPos + 1 cRetVal = '' do while .t. c = this.getChar() if c=='' return '' endif if c == '"' this.nPos = this.nPos + 1 exit endif if c == '\' this.nPos = this.nPos + 1 if (this.nPos>this.nLen) this.setError('\\ at the end of input') return '' endif c = this.getChar() if c=='' return '' endif do case case c=='"' c='"' case c=='\' c='\' case c=='/' c='/' case c=='b' c=chr(8) case c=='t' c=chr(9) case c=='n' c=chr(10) case c=='f' c=chr(12) case c=='r' c=chr(13) otherwise this.setError('Invalid escape sequence in string literal') return '' endcase endif cRetVal = cRetVal + c this.nPos = this.nPos + 1 enddo return cRetVal function parseNumber() local nStartPos,c, isInt, cNumero if not ( isdigit(this.getToken()) or this.getToken()=='-') this.setError('Expected number literal') return 0 endif nStartPos = this.nPos c = this.getChar() if c == '-' c = this.nextChar() endif if c == '0' c = this.nextChar() else if isdigit(c) c = this.nextChar() do while isdigit(c) c = this.nextChar() enddo else this.setError('Expected digit when parsing number') return 0 endif endif isInt = .t. if c=='.' c = this.nextChar() if isdigit(c) c = this.nextChar() isInt = .f. do while isDigit(c) c = this.nextChar() enddo else this.setError('Expected digit following dot comma') return 0 endif endif cNumero = substr(this.cJson, nStartPos, this.nPos - nStartPos) return val(cNumero)
function getToken() local char1 do while .t. if this.nPos > this.nLen return null endif char1 = substr(this.cJson, this.nPos, 1) if char1==' ' this.nPos = this.nPos + 1 loop endif return char1 enddo return function getChar() if this.nPos > this.nLen this.setError('Unexpected end of JSON stream') return '' endif return substr(this.cJson, this.nPos, 1) function nextChar() this.nPos = this.nPos + 1 if this.nPos > this.nLen return '' endif return substr(this.cJson, this.nPos, 1) function setError(cMsg) this.cError= 'ERROR parsing JSON at Position:'+allt(str(this.nPos,6,0))+' '+cMsg return function getError() return this.cError