Skip to content

Commit 559d4e4

Browse files
committed
Updated readme.
Changed json from proplists to maps. Removed references to depricated functionality.
1 parent 5639532 commit 559d4e4

File tree

1 file changed

+44
-54
lines changed

1 file changed

+44
-54
lines changed

README.md

+44-54
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,22 @@
33

44
## Overview
55

6-
Rec2json is a parse transform that takes a module which defines a record of
7-
the same name and adds to_json, from_json, and introspection functions. The
8-
to_json and from_json convert to and from the
9-
[proposed erlang json standard](http://www.erlang.org/eeps/eep-0018.html)
6+
Rec2json is a parse transform that takes a module which defines a record of
7+
the same name and adds to_json, from_json, and introspection functions. The
8+
to_json and from_json convert to and from the map based format used by jsx and
9+
other json encoding and decoding libraries.
1010

1111
## Features
1212

13-
* Resulting modules can be used as parameterized modules or pure erlang.
1413
* Uses a parse transform.
15-
* Limited type checking on json -> record conversion.
16-
* Limited type checking can include user defined types.
14+
* Type checking on json -> record conversion using primitive built-in types.
15+
* Type checking can be extended to include user defined types.
1716
* Atom 'undefined' fields in records optionally skipped or set to null.
1817
* Atom 'null' in json optionally converted to 'undefined'.
1918
* Post processing options on record -> json convertion.
2019
* Seed json -> record conversion with a record.
21-
* Nested json -> record and record -> json conversions for other
22-
records that have been compiled using rec2json.
20+
* Nested json -> record and record -> json conversions for other records
21+
that have been compiled using rec2json.
2322
* Generated module has accessor functions for fields and field_names for
2423
list of fields in the record.
2524
* Above feature can be surpressed, and is careful by default.
@@ -46,13 +45,11 @@ module or in an include file.
4645

4746
The transformed modules depend on the rec2json application's modules.
4847

49-
The records are unchanged and can be used normally. A record can also be
50-
used as a paramterized module, making it simple to use with the
51-
[erlydtl Django templates](https://github.com/evanmiller/erlydtl) project.
48+
The records are unchanged and can be used normally.
5249

5350
Options are passed to the rec2json parse transform through compile options.
5451
The parse transform checks for the key 'rec2json' in the compile options.
55-
The value is expected to be a proplist.
52+
The value is expected to be a proplist.
5653

5754
Options can also be passed in on a per-module basis by adding one or more
5855
`rec2json` module attributes. A `rec2json` module attribute can either be a
@@ -73,21 +70,21 @@ created. If set to false, they are not created nor exported.</td>
7370
<tr>
7471
<td>generate_setters</td> <td>true : boolean()</td> <td> If set to
7572
true, functions for setting the fields of a record are created and
76-
exported. These are of the form Field(NewVal, Record) or
77-
Record:Field(NewVal). If set to false, they are not created nor exported.
73+
exported. These are of the form Field(NewVal, Record). If set to false, they
74+
are not created nor exported.
7875
</td>
7976
</tr>
8077
<tr>
8178
<td>careful</td> <td>true : boolean()</td> <td> If set to true,
82-
rec2json's parse transform avoid altering or adding functions that are
79+
rec2json's parse transform avoids altering or adding functions that are
8380
already defined in the module. This means you can override the default
8481
to_json/1 function to call to_json/2 with a specific set of options.</td>
8582
</tr>
8683
<tr>
8784
<td>generate_type</td> <td>true : boolean()</td> <td> If set to
8885
true, a type is generated for the record, and that type is exported. In
8986
addition, a function is generated so that other rec2json records using the
90-
exported type work as expected</td>
87+
exported type work as expected.</td>
9188
</tr>
9289
<tr>
9390
<td>type_name</td> <td> ?MODULE : atom()</td> <td> If generate_type is
@@ -112,9 +109,8 @@ Record = #person{ name = <<"John">>, age = 32, spouse = undefined }.
112109
To convert a record to a json structure:
113110

114111
```erlang
115-
Json = Record:to_json().
116112
Json = person:to_json(Record).
117-
[{name, <<"John">>}, {age, 32}] = Json.
113+
#{name := <<"John">>, age := 32} = Json.
118114
```
119115

120116
The to_json function can take a list of mutators. Mutators are applied in
@@ -123,36 +119,34 @@ the order listed except {null_is_undefined}. Supported mutators are:
123119
* Turn undefined into null instead of skipping the field
124120

125121
```erlang
126-
Record:to_json([{null_is_undefined}]).
127122
person:to_json(Record, [{null_is_undefined}]).
128123
```
129124

130125
* Add a property
131126

132127
```erlang
133-
Record:to_json([{single, true}]).
134128
person:to_json(Record, [{single, true}]).
129+
person:to_json(Record, [#{single => true}).
130+
person:to_json(Record, [#{single => true, employed => true}).
135131
```
136132

137133
* Remove a property
138134

139135
```erlang
140-
Record:to_json([age]).
141136
person:to_json(Record, [age]).
142137
```
143138

144139
* Modify based only on the json
145140

146141
```erlang
147142
ModFunc = fun(Json) ->
148-
case proplists:get_value(spouse, Json) of
149-
undefined ->
150-
[{single, true} | Json];
143+
case maps:find(spouse, Json) of
144+
error ->
145+
Json#{single => true}
151146
_ ->
152-
[{single, false} | Json]
147+
Json#{single => false}
153148
end
154149
end.
155-
Record:to_json([ModFunc]).
156150
person:to_json(Record, [ModFunc]).
157151
```
158152

@@ -162,12 +156,11 @@ person:to_json(Record, [ModFunc]).
162156
ModFunc = fun(Json, Record) ->
163157
case Record#person.spouse of
164158
undefined ->
165-
[{single, true} | Json];
159+
Json#{single => true};
166160
_ ->
167-
[{single, false} | Json]
161+
Json#{single => false}
168162
end
169163
end.
170-
Record:to_json([ModFunc]).
171164
person:to_json(Record, [ModFunc]).
172165
```
173166

@@ -176,52 +169,45 @@ person:to_json(Record, [ModFunc]).
176169
Converting from a json structure to a record is just as simple:
177170

178171
```erlang
179-
{ok, Record} = person:from_json([
180-
{<<"name">>, <<"John">>},
181-
{<<"age">>, 32},
182-
{<<"spouse">>, null}
183-
]).
172+
{ok, Record} = person:from_json(#{
173+
<<"name">> => <<"John">>,
174+
<<"age">> => 32,
175+
<<"spouse">> => null
176+
}).
184177
```
185178

186-
It may be desireable to change 'null' into 'undefined' in the record:
179+
It may be desirable to change 'null' into 'undefined' in the record:
187180

188181
```erlang
189182
{ok, Record} = person:from_json(Json, [null_is_undefined]).
190183
```
191184

192-
It may be desireable to start with an existing record instead of creating
185+
It may be desirable to start with an existing record instead of creating
193186
a new one:
194187

195188
```erlang
196-
{ok, Record2} = Record:from_json(Json).
197189
{ok, Record2} = person:from_json(Json, Record).
198190
{ok, Record2} = person:from_json(Record, Json).
199-
{ok, Record2} = Record:from_json(Json, [null_is_undefined]).
200191
{ok, Record2} = person:from_json(Record, Json, [null_is_undefined]).
201192
```
202193

203-
If the json structure has a type that connot be reconciled with a type
194+
If the json structure has a type that cannot be reconciled with a type
204195
specified by the record definition, a list of fields with possible errors
205196
is returned. The record will have the data that was in the json structure.
206197
An untyped record field is the same as having the type 'any()'. There are
207-
no warings about missing properties in the json, they simply retain the
198+
no warnings about missing properties in the json, they simply retain the
208199
default value of the record.
209200

210201
```erlang
211-
{ok, Record, [age]} = person:from_json([{<<"age">>, <<"32">>}]).
202+
{ok, Record, [age]} = person:from_json(#{<<"age">> => <<"32">>}).
212203
```
213204

214205
### Including in a project
215206

216207
If all you are using is the parse_transform, simply add rec2json as a
217208
required application.
218209

219-
To be able to create modules from records without the
220-
parse transform, you will need to add the rec2json script to your path in some
221-
manner. Add a call to the rec2json script during your build (in your Makefile
222-
or rebar.config precompile hook).
223-
224-
## Type Checking and Converstion
210+
## Type Checking and Conversion
225211

226212
Type conversion attempts to be as transparent and intuitive as possible.
227213
There are some types that json does not represent directly, and some types
@@ -230,7 +216,7 @@ that have additional checking implemented.
230216
Record fields that have atoms as types will have binary values in the json
231217
checked. If the atom converted to the binary is equal to the json value, the
232218
atom value is put into the record. When converting a record to json, atom
233-
values will be converted to binaries to conform to the erlang spec.
219+
values will be converted to binaries.
234220

235221
Lists have their types checked. If there is an invalid type, the invalid
236222
type is placed in the list, but the warning message has the index of the
@@ -242,7 +228,7 @@ invalid type placed in the warning path list. For example:
242228
}).
243229

244230
type_mismatch() ->
245-
Json = [{ids, [<<"invalid">>, 3]}],
231+
Json = #{ids => [<<"invalid">>, 3]},
246232
{ok, Record, Warnings} = list_holder:from_json(Json),
247233
#list_holder{ids = [<<"invalid">>, 3]} = Record,
248234
[[ids, 1]] = Warnings.
@@ -262,7 +248,7 @@ list has the field name prepended to each. For example:
262248
}).
263249

264250
type_mismatch() ->
265-
Json = [{in_field, [{count, <<"0">>}]}],
251+
Json = #{in_field => #{count => <<"0">>}},
266252
{ok, Record, Warnings} = outer:from_json(Json),
267253
#outer{in_field = #inner{ count = <<"0">> } } = Record,
268254
[[in_filed, count]] = Warnings.
@@ -295,9 +281,9 @@ is to convert untrusted data, such as an http post request. Converting
295281
untrusted data into atoms can exhaust the erlang vm's atom table, or worse
296282
exhaust the machine's memory. Rec2json is, by default, safe.
297283

298-
It is still possilbe to apply a type to a record field so that json strings
284+
It is still possible to apply a type to a record field so that json strings
299285
will be converted to the equivalent atom using either a user defined type,
300-
or the provied `r2j_type:unsafe_atom()` type.
286+
or the provided `r2j_type:unsafe_atom()` type.
301287

302288
### User defined types
303289

@@ -313,6 +299,10 @@ For example, given the module:
313299
-module(type_example).
314300
-compile([{parse_transform, rec2json}]).
315301

302+
% These two lines exist to satisfy dialyzer.
303+
-type point() :: {number(), number()}.
304+
-export_type([point/0]).
305+
316306
-record(type_example, {
317307
some_field :: module:function(arg1, arg2),
318308
xy = {0, 0} :: type_example:point()
@@ -342,4 +332,4 @@ error is thrown.
342332

343333
## Contributing
344334

345-
Fork and submit a pull request with relevent tests.
335+
Fork and submit a pull request with relevant tests.

0 commit comments

Comments
 (0)