Source: site.view [edit]
Function name: jsonToWebL
Arguments: js
Description: Convert a JSON string toa WebL object, or return nil if syntax error
Page type: webl
Render function:  
Module: siteutil

Page source:

// var js = `{"playerSide":"O","status":"Playing","board":{"message":"I moved: B2","textRender":"    1 2 3\nA  ? ? ?\nB  ? X ?\nC  ? ? ?\n","boardPiecePositions":[{"position":"B2","piece":"X","$id":null,"$type":"games.TicTacToeBoardPiecePosition"}],"$id":null,"$type":"games.TicTacToeBoard"},"turns":[{"toPiecePosition":{"position":"B2","piece":"X","$id":null,"$type":"games.TicTacToeToPiecePosition"},"$id":null,"$type":"games.TicTacToeTurn"}],"$id":null,"$type":"games.TicTacToeGame"}`;


var getNextToken = fun (s)

   if (s == nil) or (s == "") then
      return nil
   end;

   var c = Select(s, 0, 1);
   var token = "";

   if (c member ["{","}",",",":","[","]"]) then
      token = c;
   elsif (c == "\"") or (c == "'") then
      var i = 1;
      while (i < Size(s)) and !((Select(s, i, i+1) == c) and (Select(s, i-1, i) != "\\")) do
         i = i + 1
      end;
      if (i < Size(s)) then
        token = Select(s, 0, i+1)
      end
   elsif (ToInt(c[0]) <= 32) then
      while (s != "") and (ToInt(c[0]) <= 32) do
        s = Select(s, 1, Size(s));
        c = Select(s, 0, 1);
      end;
      if s != "" then
         var tki = getNextToken(s);
         token = tki.token
      end;
   else
      var j = 1;
      while (j < Size(s)) and !(Select(s, j, j+1) member ["{","}",",",":","[","]", " ", "\"", "'"]) do
         j = j + 1
      end;
      token = Select(s, 0, j)
   end;

   return [. token = token, rest = Select(s, Size(token), Size(s)) .]
end;
  
var isNumber = fun(s)
   var c = ToInt(s) ? "string";
   if (c == "string") then
      return false
   else
      return true
   end
end;
   
var removeQuotes = fun(s)
   if Str_StartsWith(s, `"`) then
      s = Select(s, 1, Size(s))
   end;
   if Str_EndsWith(s, `"`) then
      s = Select(s, 0, Size(s)-1)
   end;
   return s
end;

var jsonToWebL = fun(js)
   var res = nil;
   var rest = "";
   var tki = getNextToken(js);
   
   if (tki != nil) and (tki.token == "{") then
      res = [. .];
      js = tki.rest;
      tki = getNextToken(js);
      var tki2;
      while (tki != nil) and (tki.token != "}") do
         var prop = nil;
         var value = nil;

         tki = getNextToken(js);
         if tki != nil then
            prop = removeQuotes(tki.token);
            js = tki.rest;          
            tki = getNextToken(js); //:
            js = tki.rest;
            if tki.token != ":" then
               return [. webl=nil, error=true, res = js .]
            end
         end;
         tki2 = jsonToWebL(js);
         if (prop != nil and tki2 != nil and tki2.error != true) then
            res[prop] := tki2.webl;
            js = tki2.rest
         else
            return [. webl=nil, error=true, res = js .]
         end;
         tki = getNextToken(js);
         if tki != nil and tki.token == "," then
            tki = getNextToken(js);
            js = tki.rest;
         elsif tki != nil and tki.token == "}" then
            js = tki.rest;
            rest = js
         else 
            return [. webl=nil, error=true, res = js .]
         end;
      end;
      if (tki != nil) then
         js = tki.rest;
         rest = js
      end   
   elsif (tki != nil) and (tki.token == "[") then
      res = [];
      js = tki.rest;
      tki = getNextToken(js);
      var tki2;
      while (tki != nil) and (tki.token != "]") do
         tki2 = jsonToWebL(js);
         if (tki2 != nil and tki2.error != true) then
            res = res + [ tki2.webl ];
            js = tki2.rest
         else
            return [. webl=nil, error=true, res = js .]
         end;
         tki = getNextToken(js);
         if tki != nil and tki.token == "," then
            tki = getNextToken(js);
            js = tki.rest;
         elsif tki != nil and tki.token == "]" then
            js = tki.rest;
            rest = js
         else 
            return [. webl=nil, error=true, res = js .]
         end;
      end;
      if (tki != nil) then
         js = tki.rest;
         rest = js
      end
   elsif tki != nil then 
     if isNumber(tki.token) then
        res = ToInt(tki.token)
     elsif tki.token == "null" then
        res = nil
     else
        res = removeQuotes(ToString(tki.token))
     end;
     rest = tki.rest
   else
     return [. webl=nil, error = true, res = js .];
   end;

   return [. webl = res, error = false, rest = rest .]
end;
  
   
var tki = jsonToWebL(js);
if tki == nil or tki.error == true then
   nil
else
   tki.webl
end;