Page 4 of 4

Re: JSON encoder and decoder

Posted: Sat Aug 03, 2013 12:56 pm
by PMV
update: 01.08.2013
+ bufix: string creation for unicode escaped characters (tab, linebreak, slash, ...) failed


@Fangbeast
Boolean values are the smalest variant of number-values. :wink:
You can use \i for that. Additional every element will save his
Datatype inside of \type. So you can use that field, too.

Code: Select all

If *out\o("items")\a(0)\o("accessInfo")\o("epub")\o("isAvailable")\type = #JSON_Type_True
  Debug "epub is available:     true"
Else
  Debug "epub is available:     false"
EndIf
I prefer the use of \type because if you are just using \i, you can't
know if it is really just a boolean value.

MFG PMV

Re: JSON encoder and decoder

Posted: Sun Aug 25, 2013 4:53 am
by nblackburn
Agreed, this would be a very useful thing to have in PB.

Re: JSON encoder and decoder

Posted: Sat Nov 02, 2013 2:50 pm
by rambodash
hey, I was using your library and discovered a small bug with 32bit integers overflowing (only effects 32bit OS)

possible fix:

Code: Select all

Procedure IsLargerThan32bitInteger(string$)
  IF len(string$) > 10 : ProcedureReturn #True : ENDIF
  IF len(string$) < 9   : ProcedureReturn #False : ENDIF
  ;2147483647
  DIM highnum(9)
  highnum(0) = 2
  highnum(1) = 1
  highnum(2) = 4
  highnum(3) = 7
  highnum(4) = 4
  highnum(5) = 8
  highnum(6) = 3
  highnum(7) = 6
  highnum(8) = 4
  highnum(9) = 7
  Define i
  Define spos = 1
  For i = 0 to ArraySize(highnum())
    IF VAL(MID(string$, spos, 1)) > highnum(i) : ProcedureReturn #True : Endif
    spos = spos + 1
  Next
  ProcedureReturn #False
EndProcedure
changes made to this section

Code: Select all


  string = PeekS(*first, (*c - *first) / SizeOf(CHARACTER))
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
    If FindString(string, ".", 1) OR IsLargerThan32bitInteger(string)
  CompilerElseIf #PB_Compiler_Processor = #PB_Processor_x64
    If FindString(string, ".", 1)  
  CompilerEndIf
    *out\s = string  ; used for JSON_encode()
    *out\f = ValD(string)
    *out\i = *out\f
    *out\type = #JSON_Type_Float
    ;Debug "Float: " + StrD(*out\f)
  ElseIf FindString(string, "e", 1)
    *out\s = string  ; used for JSON_encode()
    e = StringField(string, 2, "e")
    string = StringField(string, 1, "e")
    
    *out\f = ValD(string) * Pow(10, Val(e))
    *out\i = *out\f
    *out\type = #JSON_Type_Float
    ;Debug "Float: " + StrD(*out\f)
  Else
    *out\i = Val(string)
    *out\f = *out\i
    *out\type = #JSON_Type_Integer
    ;Debug "Integer: " + Str(*out\i)
  EndIf


Re: JSON encoder and decoder

Posted: Thu Dec 05, 2013 9:42 am
by Kukulkan
Hello,

quick question about the usage. I have loaded the following JSON (strFileList):

Code: Select all

{
 "/path/to/invoice_678432.pdf" : {
 "upload" : true,
 "meta": [ "bzu54r2bzu", "€99.95" ]
 },
 "/path/to/some/marketing_flyer.pdf" : {   },
 "/path/to/invoice_126742.pdf" : {
 "upload" : true,
 "meta": [ "Invoice#=asd21r2f00", "Total=$23" ] 
 },
 "/path/to/some/special_offer.pdf" : { "upload" : false }
}
Now parsing the content like this:

Code: Select all

*jFiles.jsonObj = JSON_decode(strFileList)
ForEach *jFiles\o()
    Protected SourcePDF.s = MapKey(*jFiles\o())
    ; (Doing some conversion here resulting in a moved file path!)
    ; THEREFORE, I LIKE TO CHANGE THE KEY NAME HERE!!!!!
Next
strFileList.s = JSON_encode(*jFiles)
JSON_free(*jFiles)
As you can see, I need to change the key name. Any idea how to do this preserving the individual content of all the elements below?

Kukulkan

Re: JSON encoder and decoder

Posted: Thu Dec 05, 2013 12:03 pm
by Kukulkan
Found no way to easily solve, but found a workaround by duplicating and swapping pointers:

Code: Select all

Protected *destFiles.jsonObj = JSON_Create() ; json object for destination
JSON_newObject(*destFiles)
*jFiles.jsonObj = JSON_decode(strFileList)
ForEach *jFiles\o()
  Protected SourcePDF.s = MapKey(*jFiles\o())
  Protected DestinationPDF.s = "some new filename"
  ; -----------------------------------
  JSON_newPair(*destFiles, DestinationPDF.s) ; create fake entry
  Copy.i = *destFiles\o(DestinationPDF.s)
  *destFiles\o(DestinationPDF.s) = *jFiles\o() ; swap pointers (real/fake)
  *jFiles\o() = Copy.i
  ; -----------------------------------
Next
strFileList.s = JSON_encode(*destFiles)
JSON_free(*jFiles)
JSON_free(*destFiles)
This did it for me. Maybe someone else can make use of it, too.

Kukulkan

Re: JSON encoder and decoder

Posted: Thu Dec 05, 2013 2:24 pm
by PMV
It is just 2 lines of code to change the key. With

Code: Select all

#JSON_UseObjectPointer = #True
PB even doesn't have to copy all elements, just writes the pointer
into the other key and delete the old key.

add this code at the end of the example inside of the JSON_Parser.pbi
file right before the line JSON_Debug(*myJSON, "")

Code: Select all

JSON_newPair(*myJSON, "Original")
*myJSON\o("Original")\s = "key to change"
*myJSON\o("Renamed") = *myJSON\o("Original") ; < create new key and copy original to new
DeleteMapElement(*myJSON\o(), "Original") ; < delete original
Hint:
If you doesn't use the pointer-way, you can remove the first line of
that example. As PB will copy all data inside of the map-element, it
will take some time if its a huge amount. Badly, there is no function to
rename a map-element to another key and preventing that.
feature request: http://www.purebasic.fr/english/viewtop ... =3&t=57600 8)

MFG PMV

Re: JSON encoder and decoder

Posted: Thu Dec 05, 2013 3:13 pm
by Kukulkan
Thanks!