defmodule JSON do | |
import String | |
def parse( content ) do | |
case parse_content(content) do | |
{ value, "" } -> value | |
{ _, _ } -> raise "crap" | |
end | |
end | |
def parse_content( << m, rest :: binary >> ) when m in ?0..?9, do: parse_number << m, rest :: binary >> | |
def parse_content( << ?", rest :: binary >> ), do: rest |> parse_string | |
def parse_content( << ?{, rest :: binary >> ), do: lstrip(rest) |> parse_object | |
def parse_content( << ?[, rest :: binary >> ), do: lstrip(rest) |> parse_array | |
def parse_string( << c, rest :: binary >> ), do: rest |> parse_string [c] | |
def parse_string( << ?", rest :: binary >>, acc ), do: { to_string(Enum.reverse(acc)), rest } | |
def parse_string( << c, rest :: binary >>, acc ), do: rest |> parse_string [c | acc] | |
def parse_number( << m, rest :: binary >> ), do: rest |> parse_number [m] | |
def parse_number( << ?., rest :: binary >>, acc ), do: rest |> parse_float [ "." | acc ] | |
def parse_number( << m, rest :: binary >>, acc ) when m in ?0..?9, do: rest |> parse_number [ m | acc ] | |
def parse_number( << rest :: binary >>, acc ), do: { Enum.reverse(acc) |> to_string |> String.to_integer, rest } | |
def parse_float( << m, rest :: binary >>, acc ) when m in ?0..?9, do: rest |> parse_float [ m | acc ] | |
def parse_float( << rest :: binary >>, acc ), do: { to_string(Enum.reverse(acc)) |> String.to_float, rest } | |
def parse_array( content ), do: parse_array([], content) | |
def parse_array( acc, << rest :: binary >> ) do | |
{ value, rest } = parse_content rest | |
acc = [ value | acc ] | |
case lstrip(rest) do | |
<< ?], rest :: binary >> -> { Enum.reverse(acc), rest } | |
<< ?,, rest :: binary >> -> parse_array acc, lstrip(rest) | |
end | |
end | |
def parse_object( content ), do: parse_object(%{}, content) | |
def parse_object( acc, << rest :: binary >> ) do | |
{ key, rest } = parse_content rest | |
{ value, rest } = lstrip(rest) |> parse_object_value | |
acc = Map.put acc, key, value | |
case lstrip(rest) do | |
<< ?}, rest :: binary >> -> { acc, rest } | |
<< ?,, rest :: binary >> -> parse_object acc, lstrip(rest) | |
end | |
end | |
def parse_object_value( << ?:, rest :: binary >> ), do: lstrip(rest) |> parse_object_value | |
def parse_object_value( rest ), do: parse_content rest | |
end | |
test = fn content -> | |
val = JSON.parse(content) | |
IO.puts "-----------------" | |
IO.puts "#{content} =>" | |
IO.inspect val | |
end | |
test.("\"asdf\"") | |
test.("0") | |
test.("1") | |
test.("10") | |
test.("18") | |
test.("1.8") | |
test.("{ \"a\": \"b\" }") | |
test.("{ \"x\": 1 }") | |
test.("{ \"q\": \"r\", \"s\": 10 }") | |
test.("{ \"q\": \"r\", \"s\": \"10\" }") | |
test.("{ \"q\": \"r\", \"s\": { \"t\": 99 } }") | |
test.("[1]") | |
test.("[1,2]") | |
test.("[1,2,3]") | |
test.("{ \"Ages\": [ 6.5, 5, 1, 1 ] }") | |
test.("{ \"Family\": [ { \"name\": \"Ryan\" }, { \"name\": \"Ben\" } ] }") | |
family = JSON.parse("{ \"Family\": [ { \"name\": \"Ryan\" }, { \"name\": \"Ben\" } ] }") | |
Enum.each family["Family"], fn person -> IO.inspect person["name"] end |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
kumekay
commented
Mar 29, 2016
I know, this sketch is old, |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I know, this sketch is old,
but your code doesn't support negative numbers
Fix is simple: replace
?0..?9
to'0123456789-'
My fixed version https://gist.github.com/pinya/01fa6c490bef8100d55dc158235f6a75