Created
May 16, 2015 00:34
-
-
Save JoshCheek/f516b64827fb94eb77a4 to your computer and use it in GitHub Desktop.
json parsers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def parse_json(json) | |
_parse_json json.chars | |
end | |
def _parse_json(chars) | |
case chars.first | |
when '{' then parse_object chars | |
when '"' then parse_string chars | |
when '[' then parse_array chars | |
when /[0-9]/ then parse_number chars | |
end | |
end | |
def parse_object(chars) | |
chars.shift # { | |
remove_whitespace(chars) | |
if chars.first == '}' | |
chars.shift | |
return Hash.new | |
end | |
object = {} | |
loop do | |
key = parse_string(chars) # "key" | |
remove_whitespace(chars) | |
chars.shift # : | |
remove_whitespace(chars) | |
object[key] = _parse_json(chars) # "value" | |
remove_whitespace(chars) | |
break if chars.shift == '}' | |
remove_whitespace(chars) | |
end | |
object | |
end | |
def parse_string(chars) | |
chars.shift | |
string = "" | |
string << chars.shift until chars.first == '"' | |
chars.shift | |
string | |
end | |
def parse_array(chars) | |
chars.shift | |
remove_whitespace(chars) | |
if chars.first == ']' | |
chars.shift | |
return Array.new | |
end | |
ary = [] | |
loop do | |
ary << _parse_json(chars) | |
remove_whitespace(chars) | |
break if chars.shift == ']' | |
remove_whitespace(chars) | |
end | |
ary | |
end | |
def parse_number(chars) | |
num_str = "" | |
num_str << chars.shift while [*'0'..'9'].include? chars.first | |
num_str.to_i | |
end | |
def remove_whitespace(chars) | |
chars.shift while chars.first == ' ' | |
end | |
parse_json '{}' # => {} | |
parse_json '[]' # => [] | |
parse_json '[1]' # => [1] | |
parse_json '{"a":"b","c":"DdDd","e":[""],"f":123}' | |
# => {"a"=>"b", "c"=>"DdDd", "e"=>[""], "f"=>123} | |
parse_json '{"abc" : 123, "def":"ghi" , "jkl" : [ 1 , 2 , 3 , [4,"5",6] ]}' | |
# => {"abc"=>123, "def"=>"ghi", "jkl"=>[1, 2, 3, [4, "5", 6]]} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'treetop' | |
Treetop.load_from_string <<GRAMMAR | |
grammar Json | |
rule document | |
space (object / array) space { | |
def to_ruby | |
elements[1].to_ruby | |
end | |
} | |
end | |
rule value | |
object / array / string / number | |
end | |
rule object | |
'{' space '}' { | |
def to_ruby | |
{} | |
end | |
} / | |
'{' | |
space | |
first:key_value_pair | |
rest:(space ',' space key_value_pair)* | |
space | |
'}' | |
{ | |
def to_ruby | |
[ first.to_ruby, *rest.map(&:to_ruby)].to_h | |
end | |
def rest | |
super.elements.map(&:key_value_pair) | |
end | |
} | |
end | |
rule key_value_pair | |
key:string space ':' space value { | |
def to_ruby | |
[key.to_ruby, value.to_ruby] | |
end | |
} | |
end | |
rule array | |
'[' space ']' { | |
def to_ruby | |
[] | |
end | |
} / | |
'[' | |
space | |
first:value | |
rest:(space ',' space value)* | |
space | |
']' | |
{ | |
def to_ruby | |
[first.to_ruby, *rest.map(&:to_ruby)] | |
end | |
def rest | |
super.elements.map(&:value) | |
end | |
} | |
end | |
rule string | |
'"' [a-zA-Z0-9]* '"' { | |
def to_ruby | |
elements[1].text_value | |
end | |
} | |
end | |
rule number | |
[0-9]* { | |
def to_ruby | |
text_value.to_i | |
end | |
} | |
end | |
rule space | |
[ \t\n]* | |
end | |
end | |
GRAMMAR | |
def parse_json(json) | |
JsonParser.new.parse(json).to_ruby | |
end | |
parse_json '{}' # => {} | |
parse_json '[]' # => [] | |
parse_json '[1]' # => [1] | |
parse_json '{"a":"b","c":"DdDd","e":[""],"f":123}' | |
# => {"a"=>"b", "c"=>"DdDd", "e"=>[""], "f"=>123} | |
parse_json '{"abc" : 123, "def":"ghi" , "jkl" : [ 1 , 2 , 3 , [4,"5",6] ]}' | |
# => {"abc"=>123, "def"=>"ghi", "jkl"=>[1, 2, 3, [4, "5", 6]]} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment