From 08d842ccf5538643a2f155bda3cbd94dce285587 Mon Sep 17 00:00:00 2001 From: pinx Date: Thu, 13 Oct 2016 15:26:53 +0200 Subject: [PATCH] Handle dashed keys, like in jsonapi.org recommendations. --- lib/poison/decoder.ex | 7 ++++++- lib/poison/encoder.ex | 7 ++++++- test/poison/decoder_test.exs | 9 +++++++++ test/poison/encoder_test.exs | 1 + 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/lib/poison/decoder.ex b/lib/poison/decoder.ex index 78e9e913..689814d2 100644 --- a/lib/poison/decoder.ex +++ b/lib/poison/decoder.ex @@ -48,7 +48,12 @@ defmodule Poison.Decode do defp transform_struct(value, keys, as, options) do Map.from_struct(as) |> Enum.reduce(%{}, fn {key, default}, acc -> - Map.put(acc, key, Map.get(value, Atom.to_string(key), default)) + string_key = if options[:dash] do + key |> Atom.to_string() |> String.replace("_", "-") + else + key |> Atom.to_string() + end + Map.put(acc, key, Map.get(value, string_key, default)) end) |> do_transform_struct(keys, as, options) end diff --git a/lib/poison/encoder.ex b/lib/poison/encoder.ex index de405bf3..ae12f560 100644 --- a/lib/poison/encoder.ex +++ b/lib/poison/encoder.ex @@ -81,9 +81,14 @@ defimpl Poison.Encoder, for: BitString do def encode("", _), do: "\"\"" def encode(string, options) do - [?", escape(string, options[:escape]), ?"] + [?", dash(string, options[:dash]) |> escape(options[:escape]), ?"] end + defp dash(string, true) when is_binary(string) do + String.replace(string, "_", "-") + end + defp dash(string, _), do: string + defp escape("", _), do: [] for {char, seq} <- Enum.zip('"\\\n\t\r\f\b', '"\\ntrfb') do diff --git a/test/poison/decoder_test.exs b/test/poison/decoder_test.exs index 39a95ea3..7117f1a1 100644 --- a/test/poison/decoder_test.exs +++ b/test/poison/decoder_test.exs @@ -23,6 +23,10 @@ defmodule Poison.DecoderTest do defstruct [:email, :telephone, call_count: 0] end + defmodule PersonDash do + defstruct [:person_name, :address, :contact, age: 42] + end + defimpl Poison.Decoder, for: Address do def decode(address, _options) do "#{address.street}, #{address.city}, #{address.state} #{address.zip}" @@ -34,6 +38,11 @@ defmodule Poison.DecoderTest do assert decode(person, as: %Person{}) == %Person{name: "Devin Torres", age: 27} end + test "decoding single :as with string-dash keys" do + person = %{"person-name" => "Devin Torres", "age" => 27} + assert decode(person, as: %PersonDash{}, dash: true) == %PersonDash{person_name: "Devin Torres", age: 27} + end + test "decoding single :as with atom keys" do person = %{name: "Devin Torres", age: 27} assert decode(person, keys: :atoms!, as: %Person{}) == %Person{name: "Devin Torres", age: 27} diff --git a/test/poison/encoder_test.exs b/test/poison/encoder_test.exs index b7a59e4b..c6e2918e 100644 --- a/test/poison/encoder_test.exs +++ b/test/poison/encoder_test.exs @@ -32,6 +32,7 @@ defmodule Poison.EncoderTest do assert to_json("\u2028\u2029", escape: :javascript) == ~s("\\u2028\\u2029") assert to_json("", escape: :html_safe) == ~s("<\\/script>") assert to_json("áéíóúàèìòùâêîôûãẽĩõũ") == ~s("áéíóúàèìòùâêîôûãẽĩõũ") + assert to_json("hello_world", dash: true) == ~s("hello-world") end test "Map" do