diff --git a/lib/json/decode.ex b/lib/json/decode.ex index caeb2c2..8cc5169 100644 --- a/lib/json/decode.ex +++ b/lib/json/decode.ex @@ -38,7 +38,7 @@ defmodule JSON.Decode do end end - # consume_value: binary -> { nil | true | false | List | HashDict | binary, binary } + # consume_value: binary -> { nil | true | false | List | Map | binary, binary } defp consume_value([ ?n, ?u, ?l, ?l | rest ]), do: { :ok, nil, rest } defp consume_value([ ?t, ?r, ?u, ?e | rest ]), do: { :ok, true, rest } @@ -98,7 +98,7 @@ defmodule JSON.Decode do consume_value_result = consume_value(after_key) case consume_value_result do {:ok, value, after_value} -> - acc = HashDict.put(acc, key, value) + acc = Map.put(acc, key, value) after_value = consume_whitespace(after_value) case after_value do [ ?, | after_comma ] -> @@ -109,7 +109,7 @@ defmodule JSON.Decode do end end - defp consume_object_contents(json) when is_list(json), do: consume_object_contents(HashDict.new, json) + defp consume_object_contents(json) when is_list(json), do: consume_object_contents(Map.new, json) defp consume_object_contents(acc, [ ?" | rest]) do consume_object_key_result = consume_object_key(rest) diff --git a/lib/json/encode.ex b/lib/json/encode.ex index 8c50cf7..b199a65 100644 --- a/lib/json/encode.ex +++ b/lib/json/encode.ex @@ -154,6 +154,33 @@ defimpl JSON.Encode, for: Record do def typeof(_), do: :object end +# Encodes maps into object +# > {:ok, "{\"a\":1,\"b\":2}"} = JSON.encode(%{a: 1, b: 2}) +defimpl JSON.Encode, for: Map do + + def to_json(map) do + {:ok, "{" <> :maps.fold( fn + (key, object, "") -> encode_pair(key, object) + (key, object, acc) -> acc <> "," <> encode_pair(key, object) + end, "", map) <> "}"} + end + + defp encode_pair(key, object) do + encode_item(key) <> ":" <> encode_item(object) + end + + defp encode_item(item) do + encode_result = JSON.Encode.to_json(item) + case encode_result do + {:ok, encoded_item} -> encoded_item + _ -> encode_result #propagate error, will trigger error in map_join + end + end + + def typeof(_), do: :object +end + + #TODO: maybe this should return the result of "inspect" ? defimpl JSON.Encode, for: Any do @any_to_json "[Elixir.Any]" diff --git a/test/json_decode_test.exs b/test/json_decode_test.exs index f13d5a1..041b0c6 100644 --- a/test/json_decode_test.exs +++ b/test/json_decode_test.exs @@ -54,9 +54,9 @@ defmodule JSONDecodeTest do decodes "float with positive exponent", "-1.22783E+4", -12278.3 decodes "float with negative exponent", "903.4e-6", 0.0009034 - decodes "empty object", "{}", HashDict.new + decodes "empty object", "{}", map.new decodes "simple object", "{\"result\": \"this is awesome\"}",\ - HashDict.new([ { "result", "this is awesome" } ]) + Map.new([ { "result", "this is awesome" } ]) decodes "empty array", " [ ] ", [] decodes "simple array", "[ 1, 2, \"three\", 4 ]", [ 1, 2, "three", 4 ] @@ -74,14 +74,14 @@ defmodule JSONDecodeTest do { \"name\": \"Éloise\" } ] }", - HashDict.new([ + Map.new([ { "name", "Rafaëlla" }, { "active", true }, { "phone", "1.415.555.0000" }, { "balance", 1.52e+5 }, { "children", [ - HashDict.new([ { "name", "Søren" } ]), - HashDict.new([ { "name", "Éloise" } ]) + Map.new([ { "name", "Søren" } ]), + Map.new([ { "name", "Éloise" } ]) ] } ]) diff --git a/test/json_encode_test.exs b/test/json_encode_test.exs index aab6d84..ef5be76 100644 --- a/test/json_encode_test.exs +++ b/test/json_encode_test.exs @@ -42,4 +42,11 @@ defmodule JSONEncodeTest do assert \ JSON.encode([result: "\\n"]) == {:ok, "{\"result\":\"\\\\n\"}"} end + + test "convert maps into correct JSON" do + assert \ + JSON.encode(%{a: 1, b: %{b1: 21}}) \ + == {:ok, "{\"a\":1,\"b\":{\"b1\":21}}"} + end + end