Τρίτη, 20 Ιουνίου 2017

Αναθεώρηση 10 (Έκδοση 8.8) και json δημιουργία δομής

Σε αυτήν την αναθεώρηση έφτιαξα διάφορα, διόρθωσα κάποια bug, και ξαναδιάβασα τη λειτουργία, γιατί χρειάστηκε να κάνω διάφορα για να μπορεί να παίξει άψογα το παρακάτω παράδειγμα,. όπου φτιάχνουμε δομές τύπου Json και διαβάβαζουμε στοιχεία από αυτές.
Το πρόγραμμα είναι στα αγγλικά. Αν θέλουμε να εξάγουμε στο πρόχειρο αντί της Print ή της Report δίνουμε την Clipboard any_string$ και το αλφαριθμητικό πάει στο πρόχειρο.

(Νέα έκδοση για να επιστρέφει όποτε θέλουμε τους αριθμούς με το σωστό σημείο δεκαδικών, ενώ κανονικά το επιστρέφει με τελεία, όπως θέλει το json)

Το πρόγραμμα είναι κάπως μεγάλο. Δημιουργούμε κλάσεις για κάθε τύπο στοιχείου της δομής. Τα αντικείμενα json είναι στην ουσία inventories (καταστάσεις), ενώ οι πίνακες είναι κανονικοί πίνακες. Και στις δυο δομές δεν βάζουμε απευθείας στοιχεία αλλά μέσω αντικειμένων όπου έχουμε βάλει μερικά πράγματα όπως για παράδειγμα το type$ για να γυρίζει τον τύπο.
Υπάρχουν δυο αντικείμενα "εργασίας". Το ένα παίρνει την δομή (την αρχική κατάσταση) και την μετατρέπει σε φορμαρισμένο json  (έχει ελεγχεθεί στο https://jsonformatter.curiousconcept.com/):
{
      "name" : "this is a name",
      "number" : 100,
      "null1" : null,
      "boolean" : true,
      "array1" : [
          100,
          [
              2,
              2.5
          ],
          3,
          4,
          5
      ],
      "object" : {
          "name" : "name2",
          "array1" : [
              "A",
              "B",
              "C"
          ]
      },
      "array2" : [
          101,
          "A"
      ],
      "string" : "Hello There\r\nSecond Line\r\n"
}

Και ένα δεύτερο το μετατρέπει σε μια παράγραφο:
{"first" : {"name" : "name2", "array1" : ["A", "B", "C"]}, "second" : {"name_2" : "name2_NAME", "array1001" : ["A1", "B2", "C3"]}, "third" : [{"byte" : 200, "bytename" : "String Alfa", "my array" : [1, 2, 3]}, 10, 5]}

Το δεύτερο αντικείμενο "εργασίας" κάνει διάβασμα σε ότι θέλουμε (χρησιμοποιεί μια κόπια του πρώτου)

Εδώ είναι η έξοδος στην οθόνη:

Flush
Form 80, 50
Inventory alfa, alfa1, alfa2, alfa3, alfa4
Class Arr {
Private:
      Dim MyValue()
Public:
      Property Type$ {Value} ="Array"
      Value {
            =.MyValue()
      }
Class:
      Module Arr (.MyValue()) {}
}
Class Null {
     Property Type$ {Value} ="Null"
     Property Str$ {Value}="null"
     Value { =0}
}
Class JString$ {
Private:
      MyValue$=""
Public:
      Property Type$ {Value} ="String"
      Property Str$ {
            Value{
                  Link parent MyValue$ to MyValue$
                  value$=quote$(string$(MyValue$ as json))
            }
      }
      Value {
            =.MyValue$
      }
Class:
      Module JString (.MyValue$) {}
}
Class Numeric {
Private:
      MyValue=0
Public:
      Property Type$ {Value} ="Number"
      Property Str$ {
            Value{
                  Link parent MyValue to MyValue
                  value$=trim$(str$(MyValue))
            }
      }
      Value {
            =.MyValue
      }
Class:
      Module Numeric (.MyValue) {}
}
Class Boolean {
Private:
      MyValue=false
Public:
      Property Type$ {Value} ="Boolean"
      Property Str$ {
            Value{
                  Link parent MyValue to MyValue
                  If MyValue Then {
                        value$="true"
                  } else value$="false"
            }
      }
      Value {
            =.MyValue
      }
Class:
      Module Boolean (.MyValue) {}
}
Class Object {
Private:
      Inventory MyValue
Public:
      Property Type$ {Value} ="Object"
      Value {
            =.MyValue
      }
Class:
      Module Object (.MyValue) {}
}
Append alfa, "name":=JString$("this is a name"), "number":=Numeric(100)
Append alfa, "null1":=Null(),  "boolean":=Boolean(True)
Append alfa, "array1":=Arr((Numeric(100),arr((Numeric(2), Numeric(2.5))),Numeric(3),Numeric(4),Numeric(5)))
Append alfa1, "name":=JString$("name2"), "array1":=Arr((JString$("A"),JString$("B"),JString$("C")))
Append alfa2, "name_2":=JString$("name2_NAME"), "array1001":=Arr((JString$("A1"),JString$("B2"),JString$("C3")))
Append alfa, "object":=Object(alfa1)
Append alfa, "array2":=Arr((Numeric(101), JString$("A") )) ', Object(alfa2,)
A$={Hello There
      Second Line
      }
Append alfa, "string":=JString$(A$)
Append alfa4, "byte":=numeric(200), "bytename":=Jstring$("String Alfa"), "my array":=Arr((Numeric(1),Numeric(2), Numeric(3)))
Append alfa3, "first":=object(alfa1), "second":=object(alfa2), "third":=Arr((object(alfa4), Numeric(10),Numeric(5)))
\\ using an object to call recuirsive in object's namespace
Class CreatSerialize$ {
      space=6
      nl1$={
      }
      Function Jarray$ (json1, n){
            \\ json1 is group type Array
                     A=json1
                  \\ A is mArray (pointer to Array)
                  nl$=.nl1$
                  if n>0 then {
                        if n<.space then n=.space
                        nl$=nl$+string$(" ", n)
                  }
                  document a$
                  a$="["
                  if n>0 then a$=nl$
                   k=each(A)
                   M=len(A)-1
                   while k {
                        For This {
                              \\ temporary group
                              temp=array(k)
                              select case temp.type$
                              case "Number", "Null","Boolean", "String"
                              a$=temp.str$
                              case "Array"
                              {
                                    nn=0
                                    if n>0 then {
                                          nn=n +.space
                                    }
                                    a$=.Jarray$(temp, nn, "")
                              }
                              case "Object"
                              {
                                   nn=0
                                    if n>0 then {
                                          nn=n +.space
                                    }
                                    a$=.Jobject$(temp, nn,"")
                              }
                              else
                                    a$=" "+temp.type$
                              end select
                               If k^<M then {
                                   a$=", "
                                    if n>0 then a$=nl$
                              } else {
                                    if n>0 then a$=.nl1$
                                    if n-.space*2>0 then a$=string$(" ", n-.space)
                              }
                        }     
                  }
            a$="]"
               =a$+letter$
      }
      Function Jobject$ (json1, n){
                        json=json1
                        \\ json has to be an object inventory
                        nl$=.nl1$
                        if n>0 then {
                              if n<.space then n=.space
                              nl$=nl$+string$(" ", n)
                        }
                        document a$
                        a$="{"
                        if n>0 then a$=nl$
                         k=each(json)
                         M=len(json)-1
                         while k {
                              a$=quote$(eval$(json, k^)) +" : "
                              select case json(k^!).type$
                              case "Array"
                              {
                                    nn=0
                                    if n>0 then {
                                          nn=n +.space
                                    }
                                    a$=.Jarray$(eval(k), nn, "")
                              }
                              case  "Boolean", "Null", "Number", "String"
                                    a$=json(k^!).str$
                              case "Object"
                              {
                                    nn=0
                                    if n>0 then {
                                          nn=n +.space
                                    }
                                    a$=.Jobject$(eval(k), nn, "")
                              }
                              else
                                    a$=" "+json( k^!).type$
                              end select
                               If k^<M then {
                                   a$=", "
                                    if n>0 then a$=nl$
                              } else {
                                    if n>0 then a$=.nl1$
                                    if n-.space*2>0 then a$=string$(" ", n-.space)
                              }
                        }
                  a$="}"
                  =a$+letter$
      }
      Class Object {
      Private:
            Inventory MyValue
      Public:
            Property Type$ {Value} ="Object"
            Value {
                  =.MyValue
            }
      Class:
            Module Object (.MyValue) {}
      }
      Value (json, n) {
                  a$=.nl1$
                  if n=0 then a$=""
                  if type$(json)<>"Group" then {
                        =.Jobject$(.Object(json), n, a$)
                  } else {
                        =.Jobject$(json, n,a$)
                  }
      }
}
Global Serialize=CreatSerialize$()
Serialize.space<=4
Group alfabeta {
Private:
      Ser$=CreatSerialize$()
      Module ReadArrayItem (temp){
             Select Case temp.type$
                  Case "String","Boolean","Number", "Null"
                  {
                        Push temp.str$
                  }
                  Case "Object"
                  {
                        if not empty then {
                           call .ReadObject temp, letter$
                        } else {
                              Push .ser.Jobject$(group(temp),0,"")
                        }
                  }
                  Case "Array"
                  {
                        if not empty then {
                              ' recursion only with Call statement for modules
                              Call .ReadArrayItem, Array(temp, number)
                        } else {
                              Push .ser.JArray$(group(temp),0,"")
                        }
                  }
                  End Select
      }
      Module ReadObject (json, id$){
      \\ take two or more parameters
            If exist(json, id$) then {
                  temp=eval(json)
                  Select Case temp.type$
                  Case "String","Boolean","Number", "Null"
                  {
                        Push temp.str$
                  }
                  Case "Object"
                  {
                        if not empty then {
                              Call .ReadObject temp, letter$
                        } else {
                              Push .ser.Jobject$(group(temp),0,"")
                        }
                  }
                  Case "Array"
                  {
                        if not empty then {
                           call .ReadArrayItem array(temp, number)
                        } else {
  
                              Push .ser.JArray$(group(temp),0,"")
                        }
                  }
                  End Select
                 } else {
                 push "none"
            }
      }
Public:
      Function UseDecimalPoint$ {
            ' use this to change standard decimal point to local decimal point character
            =str$(val(letter$),"")
      }
      Function ReadNumber$ {
                  \\ read an inventory
                  .ReadObject
                  =.UseDecimalPoint$(Letter$)
      }           
      Function ReadAnyString$ {
                  \\ read an inventory
                  .ReadObject
                  =Letter$
      }
}
Pen 11 {
     Report Serialize$(alfa, 6)
}
For alfabeta {
      Print "Read alfa"
      Report  {(alfa, "name")=}+ .ReadAnyString$(alfa, "name")
      Report  {(alfa, "array1")=} + .ReadAnyString$(alfa, "array1")
      Report  {(alfa, "array1", 0)=} + .ReadAnyString$(alfa, "array1", 0)
      Report  {(alfa, "array1", 1, 1)=} + .ReadNumber$(alfa, "array1", 1, 1)
      Report  {(alfa, "array1", 3)=} + .ReadAnyString$(alfa, "array1", 3)
      Report  {(alfa, "object")=} + .ReadAnyString$(alfa, "object")
      Report  {(alfa, "object","name")=} + .ReadAnyString$(alfa, "object","name")
      Report  {(alfa, "object", "array1")=} + .ReadAnyString$(alfa, "object", "array1")
      Report  {(alfa, "object", "array1", 2)=} + .ReadNumber$(alfa, "object", "array1", 2)
      \\ Param$() throw first and last ""
      n=row
      report {(alfa,"string")=}
      Cursor tab(1), row-1
      Pen 10 {
           Report format$(Param$(.ReadAnyString$(alfa,"string")))
      }
      Print @(0,n+2)
      Pen 11 {
            Report Serialize$(alfa3, 0)
      }
      Print "Read alfa3"
      Report  {(alfa3, "third", 0,"byte")=} + .ReadNumber$(alfa3, "third", 0,"byte")
      Report  {(alfa3, "third", 0,"my array")=} + .ReadAnyString$(alfa3, "third", 0,"my array")
      Report  {(alfa3, "third", 0,"my array",0)=} + .ReadNumber$(alfa3, "third", 0,"my array",0)
}


Document json$=Serialize$(alfa, 6)
Save.Doc json$, "alfa.json"
Wait 100
If exist("alfa.json") then {
      report "File Saved to "+Dir$+"alfa.json"
}
' by default document saved in utf8 format
' Display to notepad
Win "notepad", dir$+"alfa.json"