• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

lib/Data/H02-Apr-2007-523152

t/H02-Apr-2007-146123

ChangesH A D06-Mar-2007238 64

MANIFESTH A D02-Apr-2007176 87

META.ymlH A D02-Apr-2007315 119

Makefile.PLH A D26-Oct-20061.1 KiB4028

READMEH A D06-Mar-200710.6 KiB302227

README

1NAME
2    Data::URIEncode - Allow complex data structures to be encoded using flat
3    URIs.
4
5SYNOPSIS
6        use Data::URIEncode qw(flat_to_complex complex_to_flat);
7
8        my $data = {
9            foo => {
10                bar => 'bing',
11            },
12            baz => [123],
13        };
14
15        my $flat  = complex_to_flat($data);
16        my $query = complex_to_query($data);
17
18        # $flat looks like:
19        $flat = {
20           'foo.bar' => 'bing',
21           'baz:0'   => 123,
22        };
23
24        # $query looks like:
25        $query = "foo.bar=bing&baz:0=123"
26
27        ################################################
28
29        # put data back to how it was
30        $data = flat_to_complex($flat);
31
32        $data = query_to_complex($query);
33
34        ################################################
35
36        ### some html form somewhere
37        <form>
38        <input type="text" name="foo.bar.baz" value="brum">
39        <input type="text" name="bing:2" value="blang">
40        <input type="text" name="'key with :, ., and \''.red" value="blue">
41        </form>
42
43        ### when the form is submitted to the following code
44        use CGI;
45        use Data::URIEncode qw(query_to_complex);
46
47        my $q = CGI->new;
48        my $data = query_to_complex($q);
49
50        ### data will look like
51        $data = {
52            foo => {
53                bar => {
54                   baz = "brum",
55                },
56            },
57            bing => [
58                undef,
59                undef,
60                "blang",
61            ],
62            "key with :, ., and '" => {
63                red = "blue",
64            },
65        };
66
67DESCRIPTION
68    The world of the web works off of URI's. The Query string portion of
69    URIs already support encoding of key/value paired data - they just don't
70    natively allow for for complex data structures.
71
72    There are modules or encodings that do support arbitrarily complex data
73    structures. JSON, YAML and Data::Dumper all have their own way of
74    encoding complex structures. But then to pass them across the web, you
75    usually still have to URL encode them and pass them via a form
76    parameter.
77
78    Data::URIEncode allows for encoding and decoding complex (multi level
79    datastructures) using native Query String manipulators (such as CGI.pm).
80    It takes complex data and turns it into a flat hashref which can then be
81    turned into a URI query string using URL encoding. It also takes a flat
82    hashref of data passed in and translates it back to a complex structure.
83
84    One benefit of using Data::URIEncode is that a standard submission from
85    a standard html form can automatically be translated into complex data
86    even though it arrived in a "flat" form. This somewhat mimics the
87    abilities of XForms without introducing the complexity of XForms.
88
89    Another benefit is that sparse data can be represented in a more compact
90    form than JSON or YAML are able to provide. However, complex data with
91    long key names will be more verbose as the full data hierarchy must be
92    repeated for each value.
93
94RULES
95    For each of the following rules, the $data can be translated to $flat
96    and $query by calling complex_to_flat and complex_to_query respectively.
97    The $flat and $query can be translated back into $data using
98    flat_to_complex and query_to_complex respectively.
99
100    Simple values stay simple
101            $data  =   {key => "val", key2 => "val2"};
102            $flat  === {key => "val", key2 => "val2"};
103            $query eq  "key=val&key2=val2"
104
105    Nested hashes use a dot to modify the key.
106            $data  =   {key => {key2 => "val"}};
107            $flat  === {"key.key2" => "val"};
108            $query eq  "key.key2=val
109
110            ########
111
112            $data  =   {foo => {bar => {baz => "bling"}}};
113            $flat  === {"foo.bar.baz" = "bling"};
114            $query eq  "foo.bar.baz=bling"
115
116    Nested arrays use a colon to modify the key.
117            $data  =   {key => ["val1", "val2"]};
118            $flat  === {"key:0" => "val1", "key:1" => "val2"};
119            $query eq  "key:0=val1&key:1=val2"
120
121            ########
122
123            $data  =   {key => [ [ ["val"] ] ]};
124            $flat  === {"key:0:0" => "val"}
125            $query eq  "key:0:0=val"
126
127    Data structures can have an arrayref as the top level
128        A leading colon is used to indicate the top level node is an
129        arrayref.
130
131            $data  =   ["val1", "val2"]
132            $flat  === {":0" => "val1", ":1" => "val2"}
133            $query eq  ":0=>val1&:1=>val2"
134
135            ########
136
137            $data  =   [ [ ["val"] ] ];
138            $flat  === {":0:0:0" => "val"}
139            $query eq  ":0:0:0=val"
140
141    Keys in flat hashrefs MAY begin with a leading dot
142        A leading dot may disambiguate some cases.
143
144            $query =   ".foo=bar"
145            $flat  =   {".foo" => "bar"}
146            $data  === {foo => "bar"}
147
148    Single quotes may be used to enclose complex strings.
149        Any key containing a colon ":", a dot ".", or a single quote "'"
150        must be quoted with single quotes and have enclosed single quotes
151        escaped.
152
153            $data  =   {"foo.bar"   => "baz"}
154            $flat  === {"'foo.bar'" => "baz"}
155            $query eq  "'foo.bar'=baz"  # the ' will be swapped with %27
156
157            ########
158
159            $data  =   {"foo:bar"   => "baz"}
160            $flat  === {"'foo:bar'" => "baz"}
161            $query eq  "'foo:bar'=baz"  # the ' will be swapped with %27
162
163            ########
164
165            $data  =   {""   => "baz"}
166            $flat  === {"''" => "baz"}
167            $query eq  "''=baz"  # the ' will be swapped with %27
168
169            ########
170
171            $data  =   {"'"     => "baz"}
172            $flat  === {"'\\''" => "baz"}
173            $query eq  "'\\''=baz"  # the ' will be swapped with %27 and the \ will be replaced with %5C
174
175        Single quotes were chosen as double quotes are most commonly used in
176        HTML forms, thus allowing escaped single quotes more easily inside
177        the double quoted name.
178
179    Undefined values are not included in the flattened data
180            $data  =   {foo => undef, bar => 1}
181            $flat  === {bar => 1}
182            $query eq  "bar=1"
183
184            ########
185
186            $data  =   ["val1", undef, "val2"]
187            $flat  === {":0" => "val1", ":2" => "val2"}
188            $query eq  ":0=val1&:2=val2"
189
190    Blessed hashes and arrayrefs are dumped by default.
191        Changing the default value of the global $DUMP_BLESSED_DATA variable
192        changes the behavior.
193
194            $Data::URIEncode::DUMP_BLESSED_DATA = 1; # default
195            $data  =   {foo => bless({bar => "baz"}, "main"), one => "two"}
196            $flat  === {"foo.bar" => "baz", one => "two"}
197            $query eq  "foo.bar=baz&one=two"
198
199            ########
200
201            $Data::URIEncode::DUMP_BLESSED_DATA = 0;
202            $data  =   {foo => bless({bar => "baz"}, "main"), one => "two"}
203            $flat  === {one => "two"}
204            $query eq  "one=two"
205
206    Arrays created by flat_to_complex and query_to_complex must obey the
207    value of the $MAX_ARRAY_EXPAND variable.
208
209FUNCTIONS
210    flat_to_complex
211        Takes a hashref of simple key value pairs. Returns a data structure
212        based on the the parsed key value pairs. The parsing proceeds
213        according to the rules listed in RULES.
214
215            my $data = flat_to_complex({"foo.bar.baz:2" => "bling"});
216            # $data = {foo => {bar => {baz => [undef, undef, "bling"]}}};
217
218    complex_to_flat
219        Takes a complex data structure and turns it into a flat hashref
220        (single level key/value pairs only). The parsing proceeds according
221        to the rules listed in RULES.
222
223            my $flat = complex_to_flat({foo => ['a','b']});
224            # $flat = {"foo:0" => "a", "foo:1" => "b"});
225
226    complex_to_query
227        Similar to complex_to_flat, except that the flattened hashref is
228        then translated into query string suitable for use in a URI.
229
230            my $str = complex_to_query({foo => ['a','b']});
231            # $str eq "foo:0=a&foo:1=b"
232
233    query_to_complex
234        Takes one of a string, a reference to a string, a hash, or a CGI.pm
235        compatible object and translates it into a complex data structure.
236        Similar to flat_to_complex, exempt that a first step is taken to
237        access the query parameters from the CGI compatible object or
238        string. If a string or string ref is given, the CGI module is used
239        to parse the string into an initial flat hash of key value pairs
240        (using the param method). If another module is desired over, CGI.pm
241        you must initialize it with the data to be parsed prior to passing
242        the object to the query_to_complex function.
243
244            my $data = query_to_complex("foo.bar:0=baz");
245
246            my $data = query_to_complex(\ "foo.bar:0=baz");
247
248            my $data = query_to_complex({"foo.bar:0" => "baz"}); # same as flat_to_complex
249
250            my $cgi  = CGI->new(\ "foo.bar:0=baz");
251            my $data = query_to_complex($cgi);
252
253            my $cgi  = CGI->new; # use the values passed in from STDIN
254            my $data = query_to_complex($cgi);
255
256VARIABLES
257    $MAX_ARRAY_EXPAND
258        Default value is 100. This variable is used to determine how large
259        flat_to_complex will allow an array to be expanded beyond its
260        current size. An array can grow as large as you have memory, but
261        intermediate values must exist.
262
263        Without this value, somebody could specify foo:1000000000000=bar and
264        your server would attempt to set the 1000000000000th index of the
265        foo value to bar.
266
267        The string "foo:101=bar" would die, but the string
268        "foo:50=bar&foo:101=baz" would not die because the intermediate
269        foo->[50] increments the foo arrayref by 51 and the subsequent
270        foo->[101] call increments the foo arrayref by only 51.
271
272    $DUMP_BLESSED_DATA
273        Default is true. If true, blessed hashrefs and arrayrefs will also
274        be added to the flat data returned by complex_to_flat. If false,
275        bless hashrefs and arrayrefs will be skipped.
276
277BUGS
278    Circular refs are not detected. Any attempt to dump a struture with
279    cirular refs will result in an infinite loop. There is no immediate plan
280    to add circular ref tracking.
281
282SEE ALSO
283    All of the following have attempted to solve the same problem as
284    Data::URIEncode. All of them (including Data::URIEncode) suffer from the
285    problem of being hard to find for the specific purpose. Hash::Flatten is
286    probably the only suitable replacement for Data::URIEncode.
287
288    Hash::Flatten
289
290    CGI::Expand
291
292    HTTP::Rollup
293
294    CGI::State
295
296AUTHOR
297    Paul Seamons perlspam at seamons dot com
298
299LICENSE
300    This library may be distributed under the same terms as Perl itself.
301
302