Page 3 of 4

Re: JSON encoder and decoder

Posted: Thu Mar 28, 2013 4:35 pm
by mariosk8s
Got another patch for you.
You're not JSON escaping keys.

Code: Select all

--- a/Json2.pbi 2013-02-19 17:08:17.716628088 +0100                                       
+++ b/Json2.pbi 2013-03-28 16:32:33.984799955 +0100
@@ -253,11 +253,12 @@
           Case 't' ; tabulator
             string + Chr(9)
           Case 'u' ; 4 hex digits
+            *c + SizeOf(CHARACTER) ; eat the 'u'
             If nullByte - *c > 4 * SizeOf(CHARACTER)
               hexDigit = "$"
               ;For i = 1 To 4
                 hexDigit + PeekS(*c, 4)
-                *c + SizeOf(CHARACTER) * 4
+                *c + SizeOf(CHARACTER) * 3 ; only 3 the 4th eaten below
               ;Next
               string + Chr(Val(hexDigit))
             Else
@@ -522,6 +523,18 @@
   EndIf
 EndProcedure
 
+Procedure.s JSON_encodeString(str.s)
+  Protected tmpString.s = ReplaceString(str, "\", "\\") ; \
+  tmpString = ReplaceString(tmpString, Chr(8),  "\b") ; backspace
+  tmpString = ReplaceString(tmpString, Chr(14), "\f") ; formfeed
+  tmpString = ReplaceString(tmpString, Chr(10), "\n")  ; new line
+  tmpString = ReplaceString(tmpString, Chr(13), "\r") ; carriage return
+  tmpString = ReplaceString(tmpString, Chr(9),  "\t") ; tabulator
+  tmpString = ReplaceString(tmpString, Chr(34), "\" + Chr(34)) ; "
+  tmpString = ReplaceString(tmpString, "/",     "\/") ; /
+  ProcedureReturn tmpString
+EndProcedure
+
 Procedure.s JSON_encode(*obj.jsonObj, spaces.i = 0, type.i = #JSON_Type_Undefined)
   Protected tmpString.s
   Protected i.i
@@ -557,17 +570,8 @@
     Case #JSON_Type_Integer
       JSON_addString(Str(*obj\i))
     Case #JSON_Type_String
-      tmpString = ReplaceString(*obj\s, "\", "\\") ; \
-      tmpString = ReplaceString(tmpString, Chr(8), "\b") ; backspace
-      tmpString = ReplaceString(tmpString, Chr(14), "\f") ; formfeed
-      tmpString = ReplaceString(tmpString, Chr(10), "\n")  ; new line
-      tmpString = ReplaceString(tmpString, Chr(13), "\r") ; carriage return
-      tmpString = ReplaceString(tmpString, Chr(9), "\t") ; tabulator
-      tmpString = ReplaceString(tmpString, Chr(34), "\" + Chr(34)) ; "
-      tmpString = ReplaceString(tmpString, "/", "\/") ; /
-      
       JSON_addString(Chr(34))
-      JSON_addString(tmpString)
+      JSON_addString(JSON_encodeString(*obj\s))
       JSON_addString(Chr(34))
     Case #JSON_Type_Array
       JSON_addString("[")
@@ -595,7 +599,7 @@
         NextMapElement(*obj\o())
         JSON_addString(Space(spaces + 2))
         JSON_addString(Chr(34))
-        JSON_addString(MapKey(*obj\o()))
+        JSON_addString(JSON_encodeString(MapKey(*obj\o())))
         JSON_addString(Chr(34))
         JSON_addString(" : ")
         CompilerIf Defined(JSON_UseObjectPointer, #PB_Constant)
This patch includes my previous patch since it hasn't made it into the original post yet.

Re: JSON encoder and decoder

Posted: Thu Apr 18, 2013 10:54 pm
by PMV
update 19.04.2013
+ bugfix: encoding for unicode escaped characters (\u) failed
+ bugfix: map keys were not escaped
+ improved: escaping of strings in JSON_encode() now faster
+ improved: test code uses new possibility of CompilerIf #IsMain


Thanks again mariosk8s for bug hunting :!:
I still have not much time for testing, but i hope the new
escape-function is really faster then the previous solution
with ReplaceString(). :)

Re: JSON encoder and decoder

Posted: Fri Apr 19, 2013 7:07 am
by Kukulkan
Thanks PMV. Very good functions!

Kukulkan

Re: JSON encoder and decoder

Posted: Sat Jul 27, 2013 3:17 am
by Fangbeast
Sorry for the beginner question but, when I have a loaded string, how do I list all the available fields if I don't know in advance what they are?

Tried the below but am getting read errors at address 4 starting at "ResetMap(*out\o())"

Code: Select all

; 9780718149789		    the navigator
; 071814788x		      polar shift
; 0552151696		      digital fortress
; 0552149519		      the davinci code
; 0552151769	    pic	deception point
; 0732911206		      the lady of the sorrows

IncludeFile "JsonLib.pb"

Define GoogleJsonFile.i   = OpenFile(#PB_Any, "GoogleBookResults.txt")
Define JsonString.s       = ""
Define FileStringFormat.i = ReadStringFormat(GoogleJsonFile.i)

Define.s URLString.s
Define.s CacheFile.s

If InitNetwork()
  
 URLString.s = "https://www.googleapis.com/books/v1/volumes?projection=full&q=isbn:9780718149789"
 
  CacheFile.s = GetCurrentDirectory() + "GoogleBookResults.txt"

  If URLDownloadToFile_(0, URLString.s, CacheFile.s, 0, 0) = #S_OK
    
    Debug "Success"
    
    While Eof(GoogleJsonFile.i) = #False
      
      JsonString.s + ReadString(GoogleJsonFile.i, FileStringFormat.i) + Chr(13) + Chr(10)
      
    Wend
    
    CloseFile(GoogleJsonFile.i)
    
    Define *out.jsonObj = JSON_decode(JsonString.s)
    
    Debug MapSize(*out\o())
    
    ResetMap(*out\o())
    
    While NextMapElement(*out\o())
      
      Debug MapKey(*out\o())
      
      Debug *out\o()\o("url")\s
      
    Wend

  Else
    
    Debug "Failed"
    
  EndIf
  
Else
  
  End
  
EndIf
**EDIT** Silly me. The cachefile was being truncated at 0 bytes. D'oh! I'll just add a check for filesize.

Re: JSON encoder and decoder

Posted: Sat Jul 27, 2013 5:44 am
by USCode
Looks like C! ;-)

Very cool, thanks for sharing!

Re: JSON encoder and decoder

Posted: Sat Jul 27, 2013 10:32 am
by Fangbeast
Okay, I don't know what I am doing but am having trouble reading the output of the below string. I used my routine above to download it from google and I *thought* I could do something simple like: Debug *out\o("textSnippet")\s to show the "textSnippet": " data??

What am I doing wrong?

Code: Select all

{
 "kind": "books#volumes",
 "totalItems": 1,
 "items": [
  {
   "kind": "books#volume",
   "id": "189DPgAACAAJ",
   "etag": "M7ZWVKH/6Gc",
   "selfLink": "https://www.googleapis.com/books/v1/volumes/189DPgAACAAJ",
   "volumeInfo": {
    "title": "The Navigator",
    "subtitle": "A Kurt Austin Adventure, a Novel from the NUMA Files",
    "authors": [
     "Clive Cussler"
    ],
    "publisher": "Michael Joseph",
    "publishedDate": "2007-05-20",
    "description": "Years ago, an ancient Phoenician statue known as the Navigator was stolen from the Baghdad Museum, and there are men who would do anything to get their hands on it. The first victim is a crooked antiquities dealer, murdered in cold blood. Their second very nearly is a UN investigator who, were it not for the timely assistance of Austin and Zavala, would now be at the bottom of a very watery grave. What's so special about this statue? Austin wonders. The search for answers will take the NUMA team on an astonishing odyssey through time and space, one that encompasses no less than the lost treasures of King Solomon, a mysterious packet of documents personally encoded by Thomas Jefferson, and a top secret scientific project that could change the world forever. And that's before the surprises really begin . . .",
    "industryIdentifiers": [
     {
      "type": "ISBN_10",
      "identifier": "0718149785"
     },
     {
      "type": "ISBN_13",
      "identifier": "9780718149789"
     }
    ],
    "pageCount": 437,
    "printType": "BOOK",
    "averageRating": 3.0,
    "ratingsCount": 27,
    "contentVersion": "preview-1.0.0",
    "imageLinks": {
     "smallThumbnail": "http://bks7.books.google.com.au/books?id=189DPgAACAAJ&printsec=frontcover&img=1&zoom=5&source=gbs_api",
     "thumbnail": "http://bks7.books.google.com.au/books?id=189DPgAACAAJ&printsec=frontcover&img=1&zoom=1&source=gbs_api"
    },
    "language": "en",
    "previewLink": "http://books.google.com.au/books?id=189DPgAACAAJ&dq=isbn:9780718149789&hl=&cd=1&source=gbs_api",
    "infoLink": "http://books.google.com.au/books?id=189DPgAACAAJ&dq=isbn:9780718149789&hl=&source=gbs_api",
    "canonicalVolumeLink": "http://books.google.com.au/books/about/The_Navigator.html?hl=&id=189DPgAACAAJ"
   },
   "saleInfo": {
    "country": "AU",
    "saleability": "NOT_FOR_SALE",
    "isEbook": false
   },
   "accessInfo": {
    "country": "AU",
    "viewability": "NO_PAGES",
    "embeddable": false,
    "publicDomain": false,
    "textToSpeechPermission": "ALLOWED",
    "epub": {
     "isAvailable": false
    },
    "pdf": {
     "isAvailable": false
    },
    "webReaderLink": "http://books.google.com.au/books/reader?id=189DPgAACAAJ&hl=&printsec=frontcover&output=reader&source=gbs_api",
    "accessViewStatus": "NONE"
   },
   "searchInfo": {
    "textSnippet": "Years ago, an ancient Phoenician statue known as the Navigator was stolen from the Baghdad Museum, and there are men who would do anything to get their hands on it."
   }
  }
 ]
}

Re: JSON encoder and decoder

Posted: Sat Jul 27, 2013 5:37 pm
by StarBootics
Hello Fangbeast,

I have play a little with your code and I finally make it to work. Since I'm on linux I have loaded the json file directly from my computer not over the internet but it should work.

Code: Select all

; 9780718149789          the navigator
; 071814788x            polar shift
; 0552151696            digital fortress
; 0552149519            the davinci code
; 0552151769       pic   deception point
; 0732911206            the lady of the sorrows

IncludeFile "JsonLib.pb"

; Define GoogleJsonFile.i   = OpenFile(#PB_Any, "GoogleBookResults.txt")
; Define JsonString.s       = ""
; Define FileStringFormat.i = ReadStringFormat(GoogleJsonFile.i)

Define.s URLString.s
Define.s CacheFile.s

; If InitNetwork()
; 	
; 	URLString.s = "https://www.googleapis.com/books/v1/volumes?projection=full&q=isbn:9780718149789"
; 	
; 	CacheFile.s = GetCurrentDirectory() + "GoogleBookResults.txt"

; 	If URLDownloadToFile_(0, URLString.s, CacheFile.s, 0, 0) = #S_OK
If ReadFile(0, "book.json")
  Debug "Success"
  
  While Eof(GoogleJsonFile.i) = #False
    
    JsonString.s + ReadString(GoogleJsonFile.i, FileStringFormat.i) + Chr(13) + Chr(10)
    
  Wend
  
  CloseFile(GoogleJsonFile.i)
  
  Define *out.jsonObj = JSON_decode(JsonString.s)

  Debug "MapSize : " + Str(MapSize(*out\o()))
  
  ResetMap(*out\o())
  
  While NextMapElement(*out\o())
    
    JSON_Debug(*out.jsonObj, MapKey(*out\o()))
    
   ; Debug MapKey(*out\o()) + " : " + *out\o()\o("url")\s
    
  Wend
  
Else
  
  Debug "Failed"
  
EndIf

; Else
; 	
; 	End
; 	
; EndIf
Then the debugger output :

Code: Select all

Success
MapSize : 3
totalItems (object) : {
totalItems(int) : 1
kind (string) : books#volumes
items (array) : [
1. (object) : {
searchInfo (object) : {
textSnippet (string) : Years ago, an ancient Phoenician statue known as the Navigator was stolen from the Baghdad Museum, and there are men who would do anything to get their hands on it.
}
volumeInfo (object) : {
language (string) : en
averageRating (float) : 3
canonicalVolumeLink (string) : http://books.google.com.au/books/about/The_Navigator.html?hl=&id=189DPgAACAAJ
description (string) : Years ago, an ancient Phoenician statue known as the Navigator was stolen from the Baghdad Museum, and there are men who would do anything to get their hands on it. The first victim is a crooked antiquities dealer, murdered in cold blood. Their second very nearly is a UN investigator who, were it not for the timely assistance of Austin and Zavala, would now be at the bottom of a very watery grave. What's so special about this statue? Austin wonders. The search for answers will take the NUMA team on an astonishing odyssey through time and space, one that encompasses no less than the lost treasures of King Solomon, a mysterious packet of documents personally encoded by Thomas Jefferson, and a top secret scientific project that could change the world forever. And that's before the surprises really begin . . .
subtitle (string) : A Kurt Austin Adventure, a Novel from the NUMA Files
title (string) : The Navigator
publishedDate (string) : 2007-05-20
ratingsCount(int) : 27
infoLink (string) : http://books.google.com.au/books?id=189DPgAACAAJ&dq=isbn:9780718149789&hl=&source=gbs_api
previewLink (string) : http://books.google.com.au/books?id=189DPgAACAAJ&dq=isbn:9780718149789&hl=&cd=1&source=gbs_api
pageCount(int) : 437
printType (string) : BOOK
imageLinks (object) : {
smallThumbnail (string) : http://bks7.books.google.com.au/books?id=189DPgAACAAJ&printsec=frontcover&img=1&zoom=5&source=gbs_api
thumbnail (string) : http://bks7.books.google.com.au/books?id=189DPgAACAAJ&printsec=frontcover&img=1&zoom=1&source=gbs_api
}
industryIdentifiers (array) : [
1. (object) : {
type (string) : ISBN_10
identifier (string) : 0718149785
}
2. (object) : {
type (string) : ISBN_13
identifier (string) : 9780718149789
}
]
publisher (string) : Michael Joseph
authors (array) : [
1. (string) : Clive Cussler
]
contentVersion (string) : preview-1.0.0
}
selfLink (string) : https://www.googleapis.com/books/v1/volumes/189DPgAACAAJ
accessInfo (object) : {
country (string) : AU
textToSpeechPermission (string) : ALLOWED
pdf (object) : {
isAvailable (false)
}
epub (object) : {
isAvailable (false)
}
accessViewStatus (string) : NONE
viewability (string) : NO_PAGES
publicDomain (false)
embeddable (false)
webReaderLink (string) : http://books.google.com.au/books/reader?id=189DPgAACAAJ&hl=&printsec=frontcover&output=reader&source=gbs_api
}
kind (string) : books#volume
saleInfo (object) : {
isEbook (false)
country (string) : AU
saleability (string) : NOT_FOR_SALE
}
id (string) : 189DPgAACAAJ
etag (string) : M7ZWVKH/6Gc
}
]
}
Now how you can use information just loaded it's a different story but if you take the time to study how the JSON_Debug() work I'm pretty sure someone like you will be able to do it.

Regards
StarBootics

Re: JSON encoder and decoder

Posted: Sun Jul 28, 2013 2:01 am
by Fangbeast
Thanks StarBootics, studying the json lib, I didn't really understand it, that's why I had no idea how/why to get the output. Thanks for the pointer to the right direction.

I'm missing something though. How do I get access directly to my elements with the type in the loop as shown here in the original jsonlib page.

Code: Select all

Debug "direct Access:"
Debug "Nummer: " + *out\o("Nummer")\s
Debug "Vorname: " + *out\o("Inhaber")\o("Vorname")\s
Debug "Vorliebe 2: " + *out\o("Inhaber")\o("Vorlieben")\a(2)\s
Debug " "
I should be able to do this?

Debug "Text snippet: " + *out\o("textSnippet")\s

but nothing is returned

Re: JSON encoder and decoder

Posted: Sun Jul 28, 2013 12:08 pm
by PMV
The "textSnippet" is part of the "items"-Array, isn't it?
So you need to go through it first :wink:

it should be something like this then:

Code: Select all

Debug *out\o("items")\a(0)\o("textSnippet")\s
MFG PMV

Re: JSON encoder and decoder

Posted: Sun Jul 28, 2013 1:15 pm
by Fangbeast
PMV wrote:The "textSnippet" is part of the "items"-Array, isn't it?
So you need to go through it first :wink:

it should be something like this then:

Code: Select all

Debug *out\o("items")\a(0)\o("textSnippet")\s
MFG PMV
Sorry to be so thick, that didn't work. I find it hard to follow code where every variable is a single letter. If I understood it, I would use long variables that I could understand (grin), in the tradition of PureBasic.

This bit looks like ASCII art (*out\o("items")\a(0)\o)!!

Re: JSON encoder and decoder

Posted: Sun Jul 28, 2013 2:46 pm
by PMV
Normally, i just write variables as long as possible, but in this case,
it would result in much to long lines. I prefere lines with 70 chars instead
of 700 :mrgreen: But it is just an include, you can make your own
one by replacing the letters with the complete words. :wink:
If you understand JSON, it shouldn't be unpossible
o = object
a = array
s = string
... and so on :)

MFG PMV

Re: JSON encoder and decoder

Posted: Sun Jul 28, 2013 8:55 pm
by Fangbeast
PMV wrote:Normally, i just write variables as long as possible, but in this case,
it would result in much to long lines. I prefere lines with 70 chars instead
of 700 :mrgreen: But it is just an include, you can make your own
one by replacing the letters with the complete words. :wink:
If you understand JSON, it shouldn't be unpossible
o = object
a = array
s = string
... and so on :)
MFG PMV
Hohoho, a comedian yet. No, I don't understand json and no idea what I am doing wrong LOL. But thanks for the suggestion:):)

Re: JSON encoder and decoder

Posted: Sun Jul 28, 2013 9:37 pm
by PMV
Fangbeast wrote:
PMV wrote:The "textSnippet" is part of the "items"-Array, isn't it?
So you need to go through it first :wink:

it should be something like this then:

Code: Select all

Debug *out\o("items")\a(0)\o("textSnippet")\s
MFG PMV
Sorry to be so thick, that didn't work.
Of course, because there is another object surrounding the textSnippet :oops:
Right is this:

Code: Select all

*out\o("items")\a(0)\o("searchInfo")\o("textSnippet")\s
1. root element (*out)
2. object "items" that contains an array
3. array has just one element, so index is 0
4. object "SearchInfo" that has just one
5. object in it that is your "textSnippet"
6. access the data, in this case it is a string so it is the structure-field "s"

MFG PMV

Re: JSON encoder and decoder

Posted: Mon Jul 29, 2013 12:33 pm
by Fangbeast
I bow to your munificense and help. My tiny brain is happy! I should bowwow an animated graphic from KCC as thanks to you:):)

Bugger! I am getting a syntax error with that line. I forgot to put something in front of it LOL!

Fixed!

D'oh!! I finally thought to capture the file from the browser instead of the program. Finally I can see from the indenting which section belongs to which object!

Re: JSON encoder and decoder

Posted: Thu Aug 01, 2013 5:33 am
by Fangbeast
One last question please PMV. This section

Code: Select all

epub (object) : {
isAvailable (false)
}
I thought I could get it like this :

Code: Select all

Debug "epub is available:     " + *out\o("items")\a(0)\o("accessInfo")\o("epub")\o("isAvailable")\s
But no response as it is a true/false return (not a string \s type) and I don't know how to handle it?

Otherwise I have all the other fields coming back now (Phew!)