[XP][VX][VXA] JSON Encoder/Decoder

Started by G_G, April 17, 2012, 05:32:52 pm

Previous topic - Next topic

G_G

April 17, 2012, 05:32:52 pm Last Edit: December 20, 2012, 01:55:50 pm by Ryex
JSON Encoder/Decoder
Authors: game_guy
Version: 1.1
Type: Script Utility
Key Term: Scripting Tool



Introduction

QuoteJSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate.

This is a simple JSON Parser or Decoder. It'll take JSON thats been formatted into a string and decode it into the proper object. You can also encode certain Ruby objects into JSON.

This is a scripter's utility and isn't meant to add any new functionality or prove usefulness to non-scripters.

(Released awhile ago on RMRK)


Features


  • Decodes JSON format into ruby strings, arrays, hashes, integers, booleans.

  • Encodes Ruby objects into JSON format.




Screenshots

N/A


Demo

No demo.


Script

Spoiler: ShowHide

#===============================================================================
# JSON Encoder/Decoder
# Version 1.1
# Author: game_guy
#-------------------------------------------------------------------------------
# Intro:
# JSON (JavaScript Object Notation) is a lightweight data-interchange
# format. It is easy for humans to read and write. It is easy for machines to
# parse and generate.
# This is a simple JSON Parser or Decoder. It'll take JSON thats been
# formatted into a string and decode it into the proper object.
# This script can also encode certain ruby objects into JSON.
#
# Features:
# Decodes JSON format into ruby strings, arrays, hashes, integers, booleans.
#
# Instructions:
# This is a scripters utility. To decode JSON data, call
# JSON.decode("json string")
# -Depending on "json string", this method can return any of the values:
#  -Integer
#  -String
#  -Boolean
#  -Hash
#  -Array
#  -Nil
#
# To Encode objects, use
# JSON.encode(object)
# -This will return a string with JSON. Object can be any one of the following
#  -Integer
#  -String
#  -Boolean
#  -Hash
#  -Array
#  -Nil
#
# Credits:
# game_guy ~ Creating it.
#===============================================================================
module JSON
 
 TOKEN_NONE = 0;
 TOKEN_CURLY_OPEN = 1;
 TOKEN_CURLY_CLOSED = 2;
 TOKEN_SQUARED_OPEN = 3;
 TOKEN_SQUARED_CLOSED = 4;
 TOKEN_COLON = 5;
 TOKEN_COMMA = 6;
 TOKEN_STRING = 7;
 TOKEN_NUMBER = 8;
 TOKEN_TRUE = 9;
 TOKEN_FALSE = 10;
 TOKEN_NULL = 11;
 
 @index = 0
 @json = ""
 @length = 0
 
 def self.decode(json)
   @json = json
   @index = 0
   @length = @json.length
   return self.parse
 end
 
 def self.encode(obj)
   if obj.is_a?(Hash)
     return self.encode_hash(obj)
   elsif obj.is_a?(Array)
     return self.encode_array(obj)
   elsif obj.is_a?(Fixnum) || obj.is_a?(Float)
     return self.encode_integer(obj)
   elsif obj.is_a?(String)
     return self.encode_string(obj)
   elsif obj.is_a?(TrueClass) || obj.is_a?(FalseClass)
     return self.encode_bool(obj)
   elsif obj.is_a?(NilClass)
     return "null"
   end
   return nil
 end
 
 def self.encode_hash(hash)
   string = "{"
   hash.each_key {|key|
     string += "\"#{key}\":" + self.encode(hash[key]).to_s + ","
   }
   string[string.size - 1, 1] = "}"
   return string
 end
 
 def self.encode_array(array)
   string = "["
   array.each {|i|
     string += self.encode(i).to_s + ","
   }
   string[string.size - 1, 1] = "]"
   return string
 end
 
 def self.encode_string(string)
   return "\"#{string}\""
 end
 
 def self.encode_integer(int)
   return int.to_s
 end
 
 def self.encode_bool(bool)
   return (bool.is_a?(TrueClass) ? "true" : "false")
 end
 
 def self.next_token(debug = 0)
   char = @json[@index, 1]
   @index += 1
   case char
   when '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-'
     return TOKEN_NUMBER
   when '{'
     return TOKEN_CURLY_OPEN
   when '}'
     return TOKEN_CURLY_CLOSED
   when '"'
     return TOKEN_STRING
   when ','
     return TOKEN_COMMA
   when '['
     return TOKEN_SQUARED_OPEN
   when ']'
     return TOKEN_SQUARED_CLOSED
   when ':'
     return TOKEN_COLON
   end
   @index -= 1
   if @json[@index, 5] == "false"
     @index += 5
     return TOKEN_FALSE
   elsif @json[@index, 4] == "true"
     @index += 4
     return TOKEN_TRUE
   elsif @json[@index, 4] == "null"
     @index += 4
     return TOKEN_NULL
   end
   return TOKEN_NONE
 end
 
 def self.parse(debug = 0)
   complete = false
   while !complete
     if @index >= @length
       break
     end
     token = self.next_token
     case token
     when TOKEN_NONE
       return nil
     when TOKEN_NUMBER
       return self.parse_number
     when TOKEN_CURLY_OPEN
       return self.parse_object
     when TOKEN_STRING
       return self.parse_string
     when TOKEN_SQUARED_OPEN
       return self.parse_array
     when TOKEN_TRUE
       return true
     when TOKEN_FALSE
       return false
     when TOKEN_NULL
       return nil
     end
   end
 end
 
 def self.parse_object
   obj = {}
   complete = false
   while !complete
     token = self.next_token
     if token == TOKEN_CURLY_CLOSED
       complete = true
       break
     elsif token == TOKEN_NONE
       return nil
     elsif token == TOKEN_COMMA
     else
       name = self.parse_string
       return nil if name == nil
       token = self.next_token
       return nil if token != TOKEN_COLON
       value = self.parse
       obj[name] = value
     end
   end
   return obj
 end
 
 def self.parse_string
   complete = false
   string = ""
   while !complete
     break if @index >= @length
     char = @json[@index, 1]
     @index += 1
     case char
     when '"'
       complete = true
       break
     else
       string += char.to_s
     end
   end
   if !complete
     return nil
   end
   return string
 end
 
 def self.parse_number
   @index -= 1
   negative = @json[@index, 1] == "-" ? true : false
   string = ""
   complete = false
   while !complete
     break if @index >= @length
     char = @json[@index, 1]
     @index += 1
     case char
     when "{", "}", ":", ",", "[", "]"
       @index -= 1
       complete = true
       break
     when "0", "1", "2", '3', '4', '5', '6', '7', '8', '9'
       string += char.to_s
     end
   end
   return string.to_i
 end
 
 def self.parse_array
   obj = []
   complete = false
   while !complete
     token = self.next_token(1)
     if token == TOKEN_SQUARED_CLOSED
       complete = true
       break
     elsif token == TOKEN_NONE
       return nil
     elsif token == TOKEN_COMMA
     else
       @index -= 1
       value = self.parse
       obj.push(value)
     end
   end
   return obj
 end
 
end



Instructions

Its recommended to place this script at the top, then it can be used in any script below it. To call the parsing method, use
JSON Decode Example: ShowHide

JSON.decode(json)
Returns any of the following depending on "json":
-Integer
-String
-Boolean
-Hash
-Array
-Nil


Example:
json = '{"result":true,"profile":{"id":23,"display_name":"game_guy","group":{"id":"1","name":"Administrator","color":"#FF0000"}},"array":[0,1,2,3]}'
data = JSON.decode(json)


Output
data = {'result' => true, 'profile' => {'id' => 23, 'display_name' => 'game_guy', 'group' => {'id' => 1, 'name' => 'Administrator', 'color' => '#FF0000'}}, 'array' => [0, 1, 2, 3]}

As you can see, it supports multi-level hashes and the method returned a hash object since the string started with a "{". The first character is what defines what object its going to return.


JSON Encode Example: ShowHide
This can encode the following Ruby objects into JSON format.
Integer
Boolean
String
Hash
Array
Nil

Here's your input.
data = {'result' => true, 'profile' => {'id' => 23, 'display_name' => 'game_guy', 'group' => {'id' => 1, 'name' => 'Administrator', 'color' => '#FF0000'}}, 'array' => [0, 1, 2, 3]}
json = JSON.encode(data)


Output
'{"result":true,"profile":{"id":23,"display_name":"game_guy","group":{"id":"1","name":"Administrator","color":"#FF0000"}},"array":[0,1,2,3]}'



Compatibility

Should work with anything.


Credits and Thanks


  • game_guy ~ For creating it.




Author's Notes

Enjoy! :) You guys are lucky that VX Ace uses Ruby 1.9, or else this script wouldn't have been released. With the example code I posted, it takes a few seconds for Ruby 1.8 to parse it all.

Blizzard

April 18, 2012, 03:14:20 am #1 Last Edit: April 18, 2012, 03:17:51 am by Blizzard
Remember that you can use multiple tags in the title such as [XP][VX][VXA] to tell the database index to display a link to this script under all 3 RM categories, regardless in which section the script was actually posted. :)
Drago did it as well: http://forum.chaos-project.com/index.php?topic=11653.0
And it works just fine as you can see: http://database.chaos-project.com

EDIT: You forgot the keyterm. And you forgot it here as well: http://forum.chaos-project.com/index.php/topic,11690.0.html
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.