@@ -22,14 +22,14 @@ defmodule Poison.Encode do
22
22
alias String.Chars
23
23
alias Poison.EncodeError
24
24
25
- @ compile { :inline , encode_name: 1 }
25
+ @ compile { :inline , encode_name: 2 }
26
26
27
27
# Fast path encoding string keys
28
- defp encode_name ( value ) when is_binary ( value ) do
28
+ defp encode_name ( value , :default ) when is_binary ( value ) do
29
29
value
30
30
end
31
31
32
- defp encode_name ( value ) do
32
+ defp encode_name ( value , :default ) do
33
33
case Chars . impl_for ( value ) do
34
34
nil ->
35
35
raise EncodeError , value: value ,
@@ -38,6 +38,23 @@ defmodule Poison.Encode do
38
38
impl . to_string ( value )
39
39
end
40
40
end
41
+
42
+ defp encode_name ( value , :camel_case ) when is_binary ( value ) do
43
+ value
44
+ |> String . split ( "_" , trim: true )
45
+ |> camelize ( :first )
46
+ |> Enum . join
47
+ end
48
+
49
+ defp encode_name ( value , :camel_case ) do
50
+ value
51
+ |> encode_name ( :default )
52
+ |> encode_name ( :camel_case )
53
+ end
54
+
55
+ defp camelize ( [ ] , _ ) , do: [ ]
56
+ defp camelize ( [ h | t ] , :first ) , do: [ String . downcase ( h ) | camelize ( t , :rest ) ]
57
+ defp camelize ( [ h | t ] , _ ) , do: [ String . capitalize ( h ) , camelize ( t , :rest ) ]
41
58
end
42
59
end
43
60
end
@@ -83,13 +100,15 @@ defprotocol Poison.Encoder do
83
100
@ typep indent :: non_neg_integer
84
101
@ typep offset :: non_neg_integer
85
102
@ typep strict_keys :: boolean
103
+ @ typep format_keys :: :default | :camel_case
86
104
87
105
@ type options :: % {
88
106
optional ( :escape ) => escape ,
89
107
optional ( :pretty ) => pretty ,
90
108
optional ( :indent ) => indent ,
91
109
optional ( :offset ) => offset ,
92
110
optional ( :strict_keys ) => strict_keys ,
111
+ optional ( :format_keys ) => format_keys
93
112
}
94
113
95
114
@ spec encode ( t , options ) :: iodata
@@ -235,39 +254,55 @@ defimpl Poison.Encoder, for: Map do
235
254
236
255
def encode ( map , options ) do
237
256
map
238
- |> strict_keys ( Map . get ( options , :strict_keys , false ) )
257
+ |> strict_keys ( Map . get ( options , :strict_keys , false ) , options [ :format_keys ] || :default )
239
258
|> encode ( pretty ( options ) , options )
240
259
end
241
260
242
261
def encode ( map , true , options ) do
243
262
indent = indent ( options )
244
263
offset = offset ( options ) + indent
245
264
options = offset ( options , offset )
265
+ key_formatter = options [ :format_keys ] || :default
246
266
247
- fun = & [ ",\n " , spaces ( offset ) , Encoder.BitString . encode ( encode_name ( & 1 ) , options ) , ": " ,
267
+ fun = & [ ",\n " , spaces ( offset ) , Encoder.BitString . encode ( encode_name ( & 1 , key_formatter ) , options ) , ": " ,
248
268
Encoder . encode ( :maps . get ( & 1 , map ) , options ) | & 2 ]
249
269
[ "{\n " , tl ( :lists . foldl ( fun , [ ] , :maps . keys ( map ) ) ) , ?\n , spaces ( offset - indent ) , ?} ]
250
270
end
251
271
252
272
def encode ( map , _ , options ) do
253
- fun = & [ ?, , Encoder.BitString . encode ( encode_name ( & 1 ) , options ) , ?: ,
273
+ key_formatter = options [ :format_keys ] || :default
274
+ fun = & [ ?, , Encoder.BitString . encode ( encode_name ( & 1 , key_formatter ) , options ) , ?: ,
254
275
Encoder . encode ( :maps . get ( & 1 , map ) , options ) | & 2 ]
255
276
[ ?{ , tl ( :lists . foldl ( fun , [ ] , :maps . keys ( map ) ) ) , ?} ]
256
277
end
257
278
258
- defp strict_keys ( map , false ) , do: map
259
- defp strict_keys ( map , true ) do
279
+ defp strict_keys ( map , false , _ ) , do: map
280
+ defp strict_keys ( map , true , :default ) do
260
281
map
261
282
|> Map . keys
262
283
|> Enum . each ( fn key ->
263
- name = encode_name ( key )
284
+ name = encode_name ( key , :default )
264
285
if Map . has_key? ( map , name ) do
265
286
raise EncodeError , value: name ,
266
287
message: "duplicate key found: #{ inspect ( key ) } "
267
288
end
268
289
end )
269
290
map
270
291
end
292
+
293
+ defp strict_keys ( map , true , :camel_case ) do
294
+ map
295
+ |> Map . keys
296
+ |> Enum . reduce ( % { } , fn ( key , acc ) ->
297
+ name = encode_name ( key , :camel_case )
298
+ if Map . has_key? ( acc , name ) do
299
+ raise EncodeError , value: name ,
300
+ message: "duplicate key found: #{ inspect ( key ) } "
301
+ end
302
+ Map . put ( acc , name , :ok )
303
+ end )
304
+ map
305
+ end
271
306
end
272
307
273
308
defimpl Poison.Encoder , for: List do
0 commit comments