line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Creation date: 2007-02-19 16:54:44 |
2
|
|
|
|
|
|
|
# Authors: don |
3
|
|
|
|
|
|
|
# |
4
|
|
|
|
|
|
|
# Copyright (c) 2007-2010 Don Owens . All rights reserved. |
5
|
|
|
|
|
|
|
# |
6
|
|
|
|
|
|
|
# This is free software; you can redistribute it and/or modify it under |
7
|
|
|
|
|
|
|
# the Perl Artistic license. You should have received a copy of the |
8
|
|
|
|
|
|
|
# Artistic license with this distribution, in the file named |
9
|
|
|
|
|
|
|
# "Artistic". You may also obtain a copy from |
10
|
|
|
|
|
|
|
# http://regexguy.com/license/Artistic |
11
|
|
|
|
|
|
|
# |
12
|
|
|
|
|
|
|
# This program is distributed in the hope that it will be |
13
|
|
|
|
|
|
|
# useful, but WITHOUT ANY WARRANTY; without even the implied |
14
|
|
|
|
|
|
|
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
15
|
|
|
|
|
|
|
# PURPOSE. |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
# $Revision: 1737 $ |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
# TODO |
20
|
|
|
|
|
|
|
# * support surrogate pairs as described in http://www.ietf.org/rfc/rfc4627.txt |
21
|
|
|
|
|
|
|
# * check for first surrogate: 0xD800 => 0xDBFF |
22
|
|
|
|
|
|
|
# * check for second surrogate: 0xDC00 => 0xDFFF |
23
|
|
|
|
|
|
|
# * take code point - 0x10000, add lower 10 bits to second surrogate, add upper 10 bits to first |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
=pod |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
=head1 NAME |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
JSON::DWIW - JSON converter that Does What I Want |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
=head1 SYNOPSIS |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
use JSON::DWIW; |
34
|
|
|
|
|
|
|
my $json_obj = JSON::DWIW->new; |
35
|
|
|
|
|
|
|
my $data = $json_obj->from_json($json_str); |
36
|
|
|
|
|
|
|
my $str = $json_obj->to_json($data); |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
my ($data, $error_string) = $json_obj->from_json($json_str); |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
my $data = JSON::DWIW::deserialize($json_str); |
41
|
|
|
|
|
|
|
my $error_str = JSON::DWIW::get_error_string(); |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
use JSON::DWIW qw/deserialize_json from_json/ |
44
|
|
|
|
|
|
|
my $data = deserialize_json($json_str); |
45
|
|
|
|
|
|
|
my $error_str = JSON::DWIW::get_error_string(); |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
my $error_string = $json_obj->get_error_string; |
48
|
|
|
|
|
|
|
my $error_data = $json_obj->get_error_data; |
49
|
|
|
|
|
|
|
my $stats = $json_obj->get_stats; |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
my $data = $json_obj->from_json_file($file) |
52
|
|
|
|
|
|
|
my $ok = $json_obj->to_json_file($data, $file); |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
my $data = JSON::DWIW->from_json($json_str); |
55
|
|
|
|
|
|
|
my $str = JSON::DWIW->to_json($data); |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
my $data = JSON::DWIW->from_json($json_str, \%options); |
58
|
|
|
|
|
|
|
my $str = JSON::DWIW->to_json($data, \%options); |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
my $true_value = JSON::DWIW->true; |
61
|
|
|
|
|
|
|
my $false_value = JSON::DWIW->false; |
62
|
|
|
|
|
|
|
my $data = { var1 => "stuff", var2 => $true_value, |
63
|
|
|
|
|
|
|
var3 => $false_value, }; |
64
|
|
|
|
|
|
|
my $str = JSON::DWIW->to_json($data); |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
my $data = JSON::DWIW::deserialize($str, { start_depth => 1, |
67
|
|
|
|
|
|
|
start_depth_handler => $handler }); |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
=head1 DESCRIPTION |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
Other JSON modules require setting several parameters before |
73
|
|
|
|
|
|
|
calling the conversion methods to do what I want. This module |
74
|
|
|
|
|
|
|
does things by default that I think should be done when working |
75
|
|
|
|
|
|
|
with JSON in Perl. This module also encodes and decodes faster |
76
|
|
|
|
|
|
|
than L.pm and L in my benchmarks. |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
This means that any piece of data in Perl (assuming it's valid |
79
|
|
|
|
|
|
|
unicode) will get converted to something in JSON instead of |
80
|
|
|
|
|
|
|
throwing an exception. It also means that output will be strict |
81
|
|
|
|
|
|
|
JSON, while accepted input will be flexible, without having to |
82
|
|
|
|
|
|
|
set any options. |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
For a list of changes in recent versions, see the documentation |
85
|
|
|
|
|
|
|
for L. |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
This module can be downloaded from L. |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
=head2 Encoding |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
Perl objects get encoded as their underlying data structure, with |
92
|
|
|
|
|
|
|
the exception of L and L, which will be |
93
|
|
|
|
|
|
|
output as numbers, and L, which will get output |
94
|
|
|
|
|
|
|
as a true or false value (see the true() and false() methods). |
95
|
|
|
|
|
|
|
For example, a blessed hash ref will be represented as an object |
96
|
|
|
|
|
|
|
in JSON, a blessed array will be represented as an array. etc. A |
97
|
|
|
|
|
|
|
reference to a scalar is dereferenced and represented as the |
98
|
|
|
|
|
|
|
scalar itself. Globs, Code refs, etc., get stringified, and |
99
|
|
|
|
|
|
|
undef becomes null. |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
Scalars that have been used as both a string and a number will be |
102
|
|
|
|
|
|
|
output as a string. A reference to a reference is currently |
103
|
|
|
|
|
|
|
output as an empty string, but this may change. |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
You may notice there is a deserialize function, but not a |
106
|
|
|
|
|
|
|
serialize one. The deserialize function was written as a full |
107
|
|
|
|
|
|
|
rewrite (the parsing is in a separate, event-based library now) |
108
|
|
|
|
|
|
|
of from_json (now from_json calls deserialize). In the future, |
109
|
|
|
|
|
|
|
there will be a serialize function that is a rewrite of to_json. |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
=head2 Decoding |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
Input is expected to utf-8. When decoding, null, true, and false |
114
|
|
|
|
|
|
|
become undef, 1, and 0, repectively. Numbers that appear to be |
115
|
|
|
|
|
|
|
too long to be supported natively are converted to L |
116
|
|
|
|
|
|
|
or L objects, if you have them installed. |
117
|
|
|
|
|
|
|
Otherwise, long numbers are turned into strings to prevent data |
118
|
|
|
|
|
|
|
loss. |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
The parser is flexible in what it accepts and handles some |
121
|
|
|
|
|
|
|
things not in the JSON spec: |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=over 4 |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
=item quotes |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
Both single and double quotes are allowed for quoting a string, e.g., |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
=for pod2rst next-code-block: javascript |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
[ "string1", 'string2' ] |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
=item bare keys |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
Object/hash keys can be bare if they look like an identifier, e.g., |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
=for pod2rst next-code-block: javascript |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
{ var1: "myval1", var2: "myval2" } |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
=item extra commas |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
Extra commas in objects/hashes and arrays are ignored, e.g., |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
=for pod2rst next-code-block: javascript |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
[1,2,3,,,4,] |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
becomes a 4 element array containing 1, 2, 3, and 4. |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=item escape sequences |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
Latin1 hexadecimal escape sequences (\xHH) are accepted, as in |
154
|
|
|
|
|
|
|
Javascript. Also, the vertical tab escape \v is recognized (\u000b). |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
=item comments |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
C, C++, and shell-style comments are accepted. That is |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
=for pod2rst next-code-block: c++ |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
/* this is a comment */ |
163
|
|
|
|
|
|
|
// this is a comment |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
# this is also a comment |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
=back |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
=cut |
170
|
|
|
|
|
|
|
|
171
|
36
|
|
|
36
|
|
328778
|
use strict; |
|
36
|
|
|
|
|
90
|
|
|
36
|
|
|
|
|
1527
|
|
172
|
36
|
|
|
36
|
|
205
|
use warnings; |
|
36
|
|
|
|
|
70
|
|
|
36
|
|
|
|
|
1279
|
|
173
|
|
|
|
|
|
|
|
174
|
36
|
|
|
36
|
|
751
|
use 5.006_00; |
|
36
|
|
|
|
|
127
|
|
|
36
|
|
|
|
|
1454
|
|
175
|
|
|
|
|
|
|
|
176
|
36
|
|
|
36
|
|
22592
|
use JSON::DWIW::Boolean; |
|
36
|
|
|
|
|
94
|
|
|
36
|
|
|
|
|
1418
|
|
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
package JSON::DWIW; |
179
|
|
|
|
|
|
|
|
180
|
36
|
|
|
36
|
|
240
|
use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); |
|
36
|
|
|
|
|
350
|
|
|
36
|
|
|
|
|
3418
|
|
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
# work around utf-8 weirdness in Perl < 5.8 |
183
|
36
|
|
|
36
|
|
54369
|
use utf8; |
|
36
|
|
|
|
|
358
|
|
|
36
|
|
|
|
|
415
|
|
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
require Exporter; |
186
|
|
|
|
|
|
|
require DynaLoader; |
187
|
|
|
|
|
|
|
@ISA = qw(DynaLoader); |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
@EXPORT = ( ); |
190
|
|
|
|
|
|
|
@EXPORT_OK = (); |
191
|
|
|
|
|
|
|
%EXPORT_TAGS = (all => [ 'to_json', 'from_json', 'deserialize_json' ]); |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
Exporter::export_ok_tags('all'); |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
# change in POD as well! |
196
|
|
|
|
|
|
|
our $VERSION = '0.47'; |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
JSON::DWIW->bootstrap($VERSION); |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
{ |
202
|
|
|
|
|
|
|
package JSON::DWIW::Exporter; |
203
|
36
|
|
|
36
|
|
5614
|
use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); |
|
36
|
|
|
|
|
70
|
|
|
36
|
|
|
|
|
35435
|
|
204
|
|
|
|
|
|
|
@ISA = qw(Exporter); |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
*EXPORT = \@JSON::DWIW::EXPORT; |
207
|
|
|
|
|
|
|
*EXPORT_OK = \@JSON::DWIW::EXPORT_OK; |
208
|
|
|
|
|
|
|
*EXPORT_TAGS = \%JSON::DWIW::EXPORT_TAGS; |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
*deserialize_json = \&JSON::DWIW::deserialize_json; |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
sub import { |
213
|
36
|
|
|
36
|
|
78226
|
JSON::DWIW::Exporter->export_to_level(2, @_); |
214
|
|
|
|
|
|
|
} |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
sub to_json { |
217
|
0
|
|
|
0
|
|
0
|
return JSON::DWIW->to_json(@_); |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
sub from_json { |
221
|
|
|
|
|
|
|
# return JSON::DWIW->from_json(@_); |
222
|
1
|
|
|
1
|
|
493
|
return JSON::DWIW::deserialize(@_); |
223
|
|
|
|
|
|
|
} |
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
sub import { |
227
|
36
|
|
|
36
|
|
452
|
JSON::DWIW::Exporter::import(@_); |
228
|
|
|
|
|
|
|
} |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
{ |
231
|
|
|
|
|
|
|
# workaround for weird importing bug on some installations |
232
|
|
|
|
|
|
|
local($SIG{__DIE__}); |
233
|
36
|
|
|
36
|
|
64621
|
eval qq{ |
|
36
|
|
|
36
|
|
935148
|
|
|
36
|
|
|
|
|
316
|
|
|
36
|
|
|
|
|
777765
|
|
|
36
|
|
|
|
|
895555
|
|
|
36
|
|
|
|
|
254
|
|
234
|
|
|
|
|
|
|
use Math::BigInt; |
235
|
|
|
|
|
|
|
use Math::BigFloat; |
236
|
|
|
|
|
|
|
}; |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
=pod |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
=head1 METHODS |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
=head2 C |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
Create a new L object. |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
C<%options> is an optional hash of parameters that will change the |
249
|
|
|
|
|
|
|
bahavior of this module when encoding to JSON. You may also |
250
|
|
|
|
|
|
|
pass these options as the second argument to C and |
251
|
|
|
|
|
|
|
C. The following options are supported: |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
=head3 I |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
If set to a true value, keys in hashes will not be quoted when |
256
|
|
|
|
|
|
|
converted to JSON if they look like identifiers. This is valid |
257
|
|
|
|
|
|
|
Javascript in current browsers, but not in JSON. |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
=head3 I |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
If set to a true value, errors found when converting to or from |
262
|
|
|
|
|
|
|
JSON will result in C being called with the error message. |
263
|
|
|
|
|
|
|
The default is to not use exceptions. |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
=head3 I |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
This options indicates what should be done if bad characters are |
268
|
|
|
|
|
|
|
found, e.g., bad utf-8 sequence. The default is to return an |
269
|
|
|
|
|
|
|
error and drop all the output. |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
The following values for bad_char_policy are supported: |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
=head4 I |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
default action, i.e., drop any output built up and return an error |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
=head4 I |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
Convert to a utf-8 char using the value of the byte as a code |
280
|
|
|
|
|
|
|
point. This is basically the same as assuming the bad character |
281
|
|
|
|
|
|
|
is in latin-1 and converting it to utf-8. |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
=head4 I |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
Ignore the error and pass through the raw bytes (invalid JSON) |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
=head3 I |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
If set to a true value, escape all multi-byte characters (e.g., |
290
|
|
|
|
|
|
|
\u00e9) when converting to JSON. |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
=head3 I |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
Synonym for escape_multi_byte |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
=head3 I |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
Add white space to the output when calling to_json() to make the |
299
|
|
|
|
|
|
|
output easier for humans to read. |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
=head3 I |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
When converting from JSON, return objects for booleans so that |
304
|
|
|
|
|
|
|
"true" and "false" can be maintained when encoding and decoding. |
305
|
|
|
|
|
|
|
If this flag is set, then "true" becomes a L |
306
|
|
|
|
|
|
|
object that evaluates to true in a boolean context, and "false" |
307
|
|
|
|
|
|
|
becomes an object that evaluates to false in a boolean context. |
308
|
|
|
|
|
|
|
These objects are recognized by the to_json() method, so they |
309
|
|
|
|
|
|
|
will be output as "true" or "false" instead of "1" or "0". |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
=head3 I |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
Don't escape solidus characters ("/") in strings. The output is |
314
|
|
|
|
|
|
|
still legal JSON with this option turned on. |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
=head3 I |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
Only do required escaping in strings (solidus and quote). Tabs, |
319
|
|
|
|
|
|
|
newlines, backspaces, etc., will not be escaped with this |
320
|
|
|
|
|
|
|
optioned turned on (but the output will still be valid JSON). |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
=head3 I |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
Set to a true value to sort hash keys (alphabetically) when converting to JSON. |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
=head3 I |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
A subroutine reference to call when parsing a number. The |
329
|
|
|
|
|
|
|
subroutine will be provided one string that is the number being |
330
|
|
|
|
|
|
|
parsed. The return value from the subroutine will be used to |
331
|
|
|
|
|
|
|
populate the return data instead of converting to a number. |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
E.g., |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
my $json = '{ "a": 6.3e-10 }'; |
336
|
|
|
|
|
|
|
my $cb = sub { my ($val) = @_; return "I got the number '$val'"; }; |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
my $data = JSON::DWIW::deserialize($json, { parse_number => $cb }); |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
=head3 I |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
A subroutine reference to call when parsing a constant (true, |
343
|
|
|
|
|
|
|
false, or null). The subroutine will be provided one string that |
344
|
|
|
|
|
|
|
is the constant being parsed. The return value from the |
345
|
|
|
|
|
|
|
subroutine will be used to populate the return data instead of |
346
|
|
|
|
|
|
|
converting to a boolean or undef. See the "parse_number" option. |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
=head3 I |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
Depth at which C should be called. See L. |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
=head3 I |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
A reference to a subroutine to called when parsing and at level |
355
|
|
|
|
|
|
|
I in the data structure. When specified along with I, the |
356
|
|
|
|
|
|
|
parser does not return the entire data structure. Instead, it |
357
|
|
|
|
|
|
|
calls I for each element in the array when |
358
|
|
|
|
|
|
|
the parser is at level I. This is useful for |
359
|
|
|
|
|
|
|
parsing a very large array without loading all the data into |
360
|
|
|
|
|
|
|
memory (especially when using C). |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
E.g., with I set to 1 and I set to C<$handler>: |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
my $str = '[ { "foo": "bar", "cat": 1 }, { "concat": 1, "lambda" : [ "one", 2, 3 ] } ]'; |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
my $foo = { foo => [ ] }; |
367
|
|
|
|
|
|
|
my $handler = sub { push @{$foo->{foo}}, $_[0]; return 1; }; |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
my $data = JSON::DWIW::deserialize($str, { start_depth => 1, |
370
|
|
|
|
|
|
|
start_depth_handler => $handler }); |
371
|
|
|
|
|
|
|
print STDERR Data::Dumper->Dump([ $foo ], [ 'foo' ]) . "\n"; |
372
|
|
|
|
|
|
|
print STDERR Data::Dumper->Dump([ $data ], [ 'leftover_data' ]) . "\n"; |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
# Output |
375
|
|
|
|
|
|
|
$foo = { |
376
|
|
|
|
|
|
|
'foo' => [ |
377
|
|
|
|
|
|
|
{ |
378
|
|
|
|
|
|
|
'cat' => 1, |
379
|
|
|
|
|
|
|
'foo' => 'bar' |
380
|
|
|
|
|
|
|
}, |
381
|
|
|
|
|
|
|
{ |
382
|
|
|
|
|
|
|
'lambda' => [ |
383
|
|
|
|
|
|
|
'one', |
384
|
|
|
|
|
|
|
2, |
385
|
|
|
|
|
|
|
3 |
386
|
|
|
|
|
|
|
], |
387
|
|
|
|
|
|
|
'concat' => 1 |
388
|
|
|
|
|
|
|
} |
389
|
|
|
|
|
|
|
] |
390
|
|
|
|
|
|
|
}; |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
$leftover_data = []; |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
=cut |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
sub new { |
398
|
100
|
|
|
100
|
1
|
3137
|
my $proto = shift; |
399
|
|
|
|
|
|
|
|
400
|
100
|
|
66
|
|
|
615
|
my $self = bless {}, ref($proto) || $proto; |
401
|
100
|
|
|
|
|
165
|
my $params = shift; |
402
|
|
|
|
|
|
|
|
403
|
100
|
100
|
|
|
|
336
|
return $self unless $params; |
404
|
|
|
|
|
|
|
|
405
|
19
|
50
|
33
|
|
|
139
|
unless (defined($params) and UNIVERSAL::isa($params, 'HASH')) { |
406
|
0
|
|
|
|
|
0
|
return $self; |
407
|
|
|
|
|
|
|
} |
408
|
|
|
|
|
|
|
|
409
|
19
|
|
|
|
|
52
|
foreach my $field (qw/bare_keys use_exceptions bad_char_policy dump_vars pretty |
410
|
|
|
|
|
|
|
escape_multi_byte convert_bool detect_circular_refs |
411
|
|
|
|
|
|
|
ascii bare_solidus minimal_escaping |
412
|
|
|
|
|
|
|
parse_number parse_constant sort_keys start_depth start_depth_handler/) { |
413
|
304
|
100
|
|
|
|
692
|
if (exists($params->{$field})) { |
414
|
21
|
|
|
|
|
93
|
$self->{$field} = $params->{$field}; |
415
|
|
|
|
|
|
|
} |
416
|
|
|
|
|
|
|
} |
417
|
|
|
|
|
|
|
|
418
|
19
|
|
|
|
|
59
|
return $self; |
419
|
|
|
|
|
|
|
} |
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
=pod |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
=head2 C |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
Returns the JSON representation of $data (arbitrary |
426
|
|
|
|
|
|
|
datastructure). See http://www.json.org/ for details. |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
Called in list context, this method returns a list whose first |
429
|
|
|
|
|
|
|
element is the encoded JSON string and the second element is an |
430
|
|
|
|
|
|
|
error message, if any. If $error_msg is defined, there was a |
431
|
|
|
|
|
|
|
problem converting to JSON. You may also pass a second argument |
432
|
|
|
|
|
|
|
to to_json() that is a reference to a hash of options -- see |
433
|
|
|
|
|
|
|
new(). |
434
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
my $json_str = JSON::DWIW->to_json($data); |
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
my ($json_str, $error_msg) = JSON::DWIW->to_json($data); |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
my $json_str = JSON::DWIW->to_json($data, { use_exceptions => 1 }); |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
Aliases: toJson, toJSON, objToJson |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
=cut |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
sub to_json { |
446
|
50
|
|
|
50
|
1
|
28437
|
my $proto = shift; |
447
|
50
|
|
|
|
|
77
|
my $data; |
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
my $self; |
450
|
50
|
100
|
|
|
|
320
|
if (UNIVERSAL::isa($proto, 'JSON::DWIW')) { |
451
|
49
|
|
|
|
|
72
|
$data = shift; |
452
|
49
|
|
|
|
|
78
|
my $options = shift; |
453
|
49
|
100
|
|
|
|
110
|
if ($options) { |
454
|
10
|
100
|
66
|
|
|
64
|
if (ref($proto) and $proto->isa('HASH')) { |
455
|
3
|
50
|
|
|
|
12
|
if (UNIVERSAL::isa($options, 'HASH')) { |
456
|
3
|
|
|
|
|
20
|
$options = { %$proto, %$options }; |
457
|
|
|
|
|
|
|
} |
458
|
|
|
|
|
|
|
} |
459
|
|
|
|
|
|
|
|
460
|
10
|
|
|
|
|
47
|
$self = $proto->new($options, @_); |
461
|
|
|
|
|
|
|
} |
462
|
|
|
|
|
|
|
else { |
463
|
39
|
100
|
|
|
|
138
|
$self = ref($proto) ? $proto : $proto->new(@_); |
464
|
|
|
|
|
|
|
} |
465
|
|
|
|
|
|
|
} |
466
|
|
|
|
|
|
|
else { |
467
|
1
|
|
|
|
|
3
|
$data = $proto; |
468
|
1
|
|
|
|
|
4
|
$self = JSON::DWIW->new(@_); |
469
|
|
|
|
|
|
|
} |
470
|
|
|
|
|
|
|
|
471
|
50
|
|
|
|
|
76
|
my $error_msg; |
472
|
|
|
|
|
|
|
my $error_data; |
473
|
50
|
|
|
|
|
81
|
my $stats_data = { }; |
474
|
50
|
|
|
|
|
1394
|
my $str = _xs_to_json($self, $data, \$error_msg, \$error_data, $stats_data); |
475
|
|
|
|
|
|
|
|
476
|
50
|
50
|
|
|
|
520
|
if ($stats_data) { |
477
|
50
|
|
|
|
|
87
|
$JSON::DWIW::Last_Stats = $stats_data; |
478
|
50
|
|
|
|
|
387
|
$self->{last_stats} = $stats_data; |
479
|
|
|
|
|
|
|
} |
480
|
|
|
|
|
|
|
|
481
|
50
|
|
|
|
|
86
|
$JSON::DWIW::LastError = $error_msg; |
482
|
50
|
|
|
|
|
98
|
$self->{last_error} = $error_msg; |
483
|
|
|
|
|
|
|
|
484
|
50
|
|
|
|
|
66
|
$JSON::DWIW::LastErrorData = $error_data; |
485
|
50
|
|
|
|
|
77
|
$self->{last_error_data} = $error_data; |
486
|
|
|
|
|
|
|
|
487
|
50
|
100
|
66
|
|
|
176
|
if (defined($error_msg) and $self->{use_exceptions}) { |
488
|
1
|
|
|
|
|
8
|
die $error_msg; |
489
|
|
|
|
|
|
|
} |
490
|
49
|
100
|
|
|
|
304
|
return wantarray ? ($str, $error_msg) : $str; |
491
|
|
|
|
|
|
|
} |
492
|
|
|
|
|
|
|
{ |
493
|
36
|
|
|
36
|
|
224
|
no warnings 'once'; |
|
36
|
|
|
|
|
74
|
|
|
36
|
|
|
|
|
25760
|
|
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
*toJson = \&to_json; |
496
|
|
|
|
|
|
|
*toJSON = \&to_json; |
497
|
|
|
|
|
|
|
*objToJson = \&to_json; |
498
|
|
|
|
|
|
|
} |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
sub serialize { |
501
|
1
|
|
|
1
|
0
|
812
|
my $data = shift; |
502
|
1
|
|
50
|
|
|
13
|
my $options = shift || { }; |
503
|
|
|
|
|
|
|
|
504
|
1
|
|
|
|
|
3
|
my $error_msg; |
505
|
|
|
|
|
|
|
my $error_data; |
506
|
1
|
|
|
|
|
3
|
my $stats_data = { }; |
507
|
1
|
|
|
|
|
43
|
my $str = _xs_to_json($options, $data, \$error_msg, \$error_data, $stats_data); |
508
|
|
|
|
|
|
|
|
509
|
1
|
50
|
|
|
|
9
|
if ($stats_data) { |
510
|
1
|
|
|
|
|
4
|
$JSON::DWIW::Last_Stats = $stats_data; |
511
|
|
|
|
|
|
|
} |
512
|
|
|
|
|
|
|
|
513
|
1
|
|
|
|
|
2
|
$JSON::DWIW::LastError = $error_msg; |
514
|
|
|
|
|
|
|
|
515
|
1
|
|
|
|
|
2
|
$JSON::DWIW::LastErrorData = $error_data; |
516
|
|
|
|
|
|
|
|
517
|
1
|
|
|
|
|
5
|
return $str; |
518
|
|
|
|
|
|
|
} |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
# total process size in pages |
521
|
|
|
|
|
|
|
sub get_proc_size { |
522
|
0
|
0
|
|
0
|
0
|
0
|
if ($^O eq 'linux') { |
523
|
0
|
|
|
|
|
0
|
my $statm_path = "/proc/$$/statm"; |
524
|
0
|
0
|
|
|
|
0
|
if (-e $statm_path) { |
525
|
0
|
0
|
|
|
|
0
|
open(my $in_fh, '<', $statm_path) or return undef; |
526
|
0
|
|
|
|
|
0
|
my $statm = <$in_fh>; |
527
|
0
|
|
|
|
|
0
|
close $in_fh; |
528
|
|
|
|
|
|
|
|
529
|
0
|
|
|
|
|
0
|
my @fields = split /\s+/, $statm; |
530
|
|
|
|
|
|
|
|
531
|
0
|
|
|
|
|
0
|
return $fields[0]; |
532
|
|
|
|
|
|
|
} |
533
|
|
|
|
|
|
|
} |
534
|
|
|
|
|
|
|
|
535
|
0
|
|
|
|
|
0
|
return undef; |
536
|
|
|
|
|
|
|
} |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
=pod |
539
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
=head2 C |
541
|
|
|
|
|
|
|
|
542
|
|
|
|
|
|
|
Returns the Perl data structure for the given JSON string. The |
543
|
|
|
|
|
|
|
value for true becomes 1, false becomes 0, and null gets |
544
|
|
|
|
|
|
|
converted to undef. |
545
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
This function should not be called as a method (for performance |
547
|
|
|
|
|
|
|
reasons). Unlike C, it returns a single value, the |
548
|
|
|
|
|
|
|
data structure resulting from the conversion. If the return |
549
|
|
|
|
|
|
|
value is undef, check the result of the C |
550
|
|
|
|
|
|
|
function/method to see if an error is defined. |
551
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
=head2 C |
553
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
Same as deserialize, except that it takes a file as an argument. |
555
|
|
|
|
|
|
|
On Unix, this mmap's the file, so it does not load a big file |
556
|
|
|
|
|
|
|
into memory all at once, and does less buffer copying. |
557
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
=cut |
559
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
=pod |
561
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
=head2 C |
563
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
Similar to C, but expects to be called as a method. |
565
|
|
|
|
|
|
|
|
566
|
|
|
|
|
|
|
Called in list context, this method returns a list whose first |
567
|
|
|
|
|
|
|
element is the data and the second element is the error message, |
568
|
|
|
|
|
|
|
if any. If C<$error_msg> is defined, there was a problem parsing |
569
|
|
|
|
|
|
|
the JSON string, and C<$data> will be undef. You may also pass a |
570
|
|
|
|
|
|
|
second argument to C that is a reference to a hash of |
571
|
|
|
|
|
|
|
options -- see C. |
572
|
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
my $data = from_json($json_str) |
574
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
my ($data, $error_msg) = from_json($json_str) |
576
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
|
578
|
|
|
|
|
|
|
Aliases: fromJson, fromJSON, jsonToObj |
579
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
=cut |
581
|
|
|
|
|
|
|
|
582
|
|
|
|
|
|
|
sub from_json { |
583
|
60
|
|
|
60
|
1
|
21692
|
my $proto = shift; |
584
|
60
|
|
|
|
|
89
|
my $json; |
585
|
|
|
|
|
|
|
my $self; |
586
|
|
|
|
|
|
|
|
587
|
60
|
100
|
|
|
|
287
|
if (UNIVERSAL::isa($proto, 'JSON::DWIW')) { |
588
|
58
|
|
|
|
|
115
|
$json = shift; |
589
|
58
|
|
|
|
|
78
|
my $options = shift; |
590
|
58
|
100
|
|
|
|
124
|
if ($options) { |
591
|
4
|
50
|
33
|
|
|
18
|
if (ref($proto) and $proto->isa('HASH')) { |
592
|
0
|
0
|
|
|
|
0
|
if (UNIVERSAL::isa($options, 'HASH')) { |
593
|
0
|
|
|
|
|
0
|
$options = { %$proto, %$options }; |
594
|
|
|
|
|
|
|
} |
595
|
|
|
|
|
|
|
} |
596
|
|
|
|
|
|
|
|
597
|
4
|
|
|
|
|
17
|
$self = $proto->new($options, @_); |
598
|
|
|
|
|
|
|
} |
599
|
|
|
|
|
|
|
else { |
600
|
54
|
100
|
|
|
|
335
|
$self = ref($proto) ? $proto : $proto->new(@_); |
601
|
|
|
|
|
|
|
} |
602
|
|
|
|
|
|
|
} |
603
|
|
|
|
|
|
|
else { |
604
|
2
|
|
|
|
|
4
|
$json = $proto; |
605
|
2
|
|
|
|
|
9
|
$self = JSON::DWIW->new(@_); |
606
|
|
|
|
|
|
|
} |
607
|
|
|
|
|
|
|
|
608
|
60
|
|
|
|
|
77
|
my $data; |
609
|
60
|
100
|
|
|
|
192
|
if (%$self) { |
610
|
18
|
|
|
|
|
663
|
$data = JSON::DWIW::deserialize($json, $self); |
611
|
|
|
|
|
|
|
} |
612
|
|
|
|
|
|
|
else { |
613
|
42
|
|
|
|
|
2313
|
$data = JSON::DWIW::deserialize($json); |
614
|
|
|
|
|
|
|
} |
615
|
|
|
|
|
|
|
|
616
|
56
|
|
|
|
|
397
|
$self->{last_error} = $JSON::DWIW::LastError; |
617
|
56
|
|
|
|
|
100
|
$self->{last_error_data} = $JSON::DWIW::LastErrorData; |
618
|
56
|
|
|
|
|
88
|
$self->{last_stats} = $JSON::DWIW::Last_Stats; |
619
|
|
|
|
|
|
|
|
620
|
56
|
50
|
66
|
|
|
227
|
if (defined($JSON::DWIW::LastError) and $self->{use_exceptions}) { |
621
|
0
|
|
|
|
|
0
|
die $JSON::DWIW::LastError; |
622
|
|
|
|
|
|
|
} |
623
|
|
|
|
|
|
|
|
624
|
56
|
100
|
|
|
|
325
|
return wantarray ? ($data, $JSON::DWIW::LastError) : $data; |
625
|
|
|
|
|
|
|
} |
626
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
{ |
628
|
36
|
|
|
36
|
|
616
|
no warnings 'once'; |
|
36
|
|
|
|
|
75
|
|
|
36
|
|
|
|
|
109771
|
|
629
|
|
|
|
|
|
|
*jsonToObj = \&from_json; |
630
|
|
|
|
|
|
|
*fromJson = \&from_json; |
631
|
|
|
|
|
|
|
*fromJSON = \&from_json; |
632
|
|
|
|
|
|
|
} |
633
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
=pod |
635
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
=head2 C |
637
|
|
|
|
|
|
|
|
638
|
|
|
|
|
|
|
Similar to C, except that it expects to be |
639
|
|
|
|
|
|
|
called a a method, and it also returns the error, if any, when called |
640
|
|
|
|
|
|
|
in list context. |
641
|
|
|
|
|
|
|
|
642
|
|
|
|
|
|
|
my ($data, $error_msg) = $json->from_json_file($file, \%options) |
643
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
=cut |
645
|
|
|
|
|
|
|
sub from_json_file { |
646
|
22
|
|
|
22
|
1
|
4552
|
my $proto = shift; |
647
|
22
|
|
|
|
|
31
|
my $file; |
648
|
|
|
|
|
|
|
my $self; |
649
|
|
|
|
|
|
|
|
650
|
22
|
50
|
|
|
|
94
|
if (UNIVERSAL::isa($proto, 'JSON::DWIW')) { |
651
|
22
|
|
|
|
|
29
|
$file = shift; |
652
|
22
|
|
|
|
|
27
|
my $options = shift; |
653
|
22
|
50
|
|
|
|
36
|
if ($options) { |
654
|
0
|
0
|
0
|
|
|
0
|
if (ref($proto) and $proto->isa('HASH')) { |
655
|
0
|
0
|
|
|
|
0
|
if (UNIVERSAL::isa($options, 'HASH')) { |
656
|
0
|
|
|
|
|
0
|
$options = { %$proto, %$options }; |
657
|
|
|
|
|
|
|
} |
658
|
|
|
|
|
|
|
} |
659
|
|
|
|
|
|
|
|
660
|
0
|
|
|
|
|
0
|
$self = $proto->new($options, @_); |
661
|
|
|
|
|
|
|
} |
662
|
|
|
|
|
|
|
else { |
663
|
22
|
100
|
|
|
|
73
|
$self = ref($proto) ? $proto : $proto->new(@_); |
664
|
|
|
|
|
|
|
} |
665
|
|
|
|
|
|
|
} |
666
|
|
|
|
|
|
|
else { |
667
|
0
|
|
|
|
|
0
|
$file = $proto; |
668
|
0
|
|
|
|
|
0
|
$self = JSON::DWIW->new(@_); |
669
|
|
|
|
|
|
|
} |
670
|
|
|
|
|
|
|
|
671
|
22
|
|
|
|
|
24
|
my $data; |
672
|
22
|
50
|
|
|
|
47
|
if (%$self) { |
673
|
0
|
|
|
|
|
0
|
$data = JSON::DWIW::deserialize_file($file, $self); |
674
|
|
|
|
|
|
|
} |
675
|
|
|
|
|
|
|
else { |
676
|
22
|
|
|
|
|
2030
|
$data = JSON::DWIW::deserialize_file($file); |
677
|
|
|
|
|
|
|
} |
678
|
|
|
|
|
|
|
|
679
|
22
|
|
|
|
|
915
|
$self->{last_error} = $JSON::DWIW::LastError; |
680
|
22
|
|
|
|
|
37
|
$self->{last_error_data} = $JSON::DWIW::LastErrorData; |
681
|
22
|
|
|
|
|
28
|
$self->{last_stats} = $JSON::DWIW::Last_Stats; |
682
|
|
|
|
|
|
|
|
683
|
22
|
50
|
66
|
|
|
99
|
if (defined($JSON::DWIW::LastError) and $self->{use_exceptions}) { |
684
|
0
|
|
|
|
|
0
|
die $JSON::DWIW::LastError; |
685
|
|
|
|
|
|
|
} |
686
|
|
|
|
|
|
|
|
687
|
22
|
100
|
|
|
|
144
|
return wantarray ? ($data, $JSON::DWIW::LastError) : $data; |
688
|
|
|
|
|
|
|
} |
689
|
|
|
|
|
|
|
|
690
|
|
|
|
|
|
|
=pod |
691
|
|
|
|
|
|
|
|
692
|
|
|
|
|
|
|
=head2 C |
693
|
|
|
|
|
|
|
|
694
|
|
|
|
|
|
|
Converts C<$data> to JSON and writes the result to the file C<$file>. |
695
|
|
|
|
|
|
|
Currently, this is simply a convenience routine that converts |
696
|
|
|
|
|
|
|
the data to a JSON string and then writes it to the file. |
697
|
|
|
|
|
|
|
|
698
|
|
|
|
|
|
|
my ($ok, $error) = $json->to_json_file($data, $file, \%options); |
699
|
|
|
|
|
|
|
|
700
|
|
|
|
|
|
|
=cut |
701
|
|
|
|
|
|
|
sub to_json_file { |
702
|
0
|
|
|
0
|
1
|
0
|
my $proto = shift; |
703
|
0
|
|
|
|
|
0
|
my $file; |
704
|
|
|
|
|
|
|
my $data; |
705
|
0
|
|
|
|
|
0
|
my $self; |
706
|
|
|
|
|
|
|
|
707
|
0
|
0
|
|
|
|
0
|
if (UNIVERSAL::isa($proto, 'JSON::DWIW')) { |
708
|
0
|
|
|
|
|
0
|
$data = shift; |
709
|
0
|
|
|
|
|
0
|
$file = shift; |
710
|
0
|
|
|
|
|
0
|
my $options = shift; |
711
|
0
|
0
|
|
|
|
0
|
if ($options) { |
712
|
0
|
0
|
0
|
|
|
0
|
if (ref($proto) and $proto->isa('HASH')) { |
713
|
0
|
0
|
|
|
|
0
|
if (UNIVERSAL::isa($options, 'HASH')) { |
714
|
0
|
|
|
|
|
0
|
$options = { %$proto, %$options }; |
715
|
|
|
|
|
|
|
} |
716
|
|
|
|
|
|
|
} |
717
|
|
|
|
|
|
|
|
718
|
0
|
|
|
|
|
0
|
$self = $proto->new($options, @_); |
719
|
|
|
|
|
|
|
} |
720
|
|
|
|
|
|
|
else { |
721
|
0
|
0
|
|
|
|
0
|
$self = ref($proto) ? $proto : $proto->new(@_); |
722
|
|
|
|
|
|
|
} |
723
|
|
|
|
|
|
|
} |
724
|
|
|
|
|
|
|
else { |
725
|
0
|
|
|
|
|
0
|
$data = $proto; |
726
|
0
|
|
|
|
|
0
|
$file = shift; |
727
|
0
|
|
|
|
|
0
|
$self = JSON::DWIW->new(@_); |
728
|
|
|
|
|
|
|
} |
729
|
|
|
|
|
|
|
|
730
|
0
|
|
|
|
|
0
|
my $out_fh; |
731
|
0
|
0
|
|
|
|
0
|
unless (open($out_fh, '>', $file)) { |
732
|
0
|
|
|
|
|
0
|
my $msg = "JSON::DWIW v$VERSION - couldn't open output file $file"; |
733
|
0
|
0
|
|
|
|
0
|
if ($self->{use_exceptions}) { |
734
|
0
|
|
|
|
|
0
|
die $msg; |
735
|
|
|
|
|
|
|
} else { |
736
|
0
|
0
|
|
|
|
0
|
return wantarray ? ( undef, $msg ) : undef; |
737
|
|
|
|
|
|
|
} |
738
|
|
|
|
|
|
|
} |
739
|
|
|
|
|
|
|
|
740
|
0
|
0
|
|
|
|
0
|
if ($] >= 5.008) { |
741
|
0
|
|
|
|
|
0
|
binmode($out_fh, 'utf8'); |
742
|
|
|
|
|
|
|
} |
743
|
|
|
|
|
|
|
|
744
|
0
|
|
|
|
|
0
|
my $error_msg; |
745
|
|
|
|
|
|
|
my $error_data; |
746
|
0
|
|
|
|
|
0
|
my $stats_data = { }; |
747
|
0
|
|
|
|
|
0
|
my $str = _xs_to_json($self, $data, \$error_msg, \$error_data, $stats_data); |
748
|
|
|
|
|
|
|
|
749
|
0
|
0
|
|
|
|
0
|
if ($stats_data) { |
750
|
0
|
|
|
|
|
0
|
$JSON::DWIW::Last_Stats = $stats_data; |
751
|
0
|
|
|
|
|
0
|
$self->{last_stats} = $stats_data; |
752
|
|
|
|
|
|
|
} |
753
|
|
|
|
|
|
|
|
754
|
0
|
|
|
|
|
0
|
$JSON::DWIW::LastError = $error_msg; |
755
|
0
|
|
|
|
|
0
|
$self->{last_error} = $error_msg; |
756
|
|
|
|
|
|
|
|
757
|
0
|
|
|
|
|
0
|
$JSON::DWIW::LastErrorData = $error_data; |
758
|
0
|
|
|
|
|
0
|
$self->{last_error_data} = $error_data; |
759
|
|
|
|
|
|
|
|
760
|
|
|
|
|
|
|
|
761
|
0
|
0
|
0
|
|
|
0
|
if (defined($error_msg) and $self->{use_exceptions}) { |
762
|
0
|
|
|
|
|
0
|
die $error_msg; |
763
|
|
|
|
|
|
|
} |
764
|
|
|
|
|
|
|
|
765
|
0
|
0
|
|
|
|
0
|
if ($error_msg) { |
766
|
0
|
0
|
|
|
|
0
|
return wantarray ? (undef, $error_msg) : undef; |
767
|
|
|
|
|
|
|
} |
768
|
|
|
|
|
|
|
|
769
|
0
|
|
|
|
|
0
|
print $out_fh $str; |
770
|
0
|
|
|
|
|
0
|
close $out_fh; |
771
|
|
|
|
|
|
|
|
772
|
0
|
0
|
|
|
|
0
|
return wantarray ? (1, $error_msg) : 1; |
773
|
|
|
|
|
|
|
} |
774
|
|
|
|
|
|
|
|
775
|
|
|
|
|
|
|
sub parse_mmap_file { |
776
|
0
|
|
|
0
|
0
|
0
|
my $proto = shift; |
777
|
0
|
|
|
|
|
0
|
my $file = shift; |
778
|
|
|
|
|
|
|
|
779
|
0
|
|
|
|
|
0
|
my $error_msg; |
780
|
0
|
|
|
|
|
0
|
my $self = $proto->new; |
781
|
|
|
|
|
|
|
|
782
|
0
|
|
|
|
|
0
|
my $data = _parse_mmap_file($self, $file, \$error_msg); |
783
|
0
|
0
|
|
|
|
0
|
if ($error_msg) { |
784
|
0
|
0
|
|
|
|
0
|
return wantarray ? (undef, $error_msg) : undef; |
785
|
|
|
|
|
|
|
} |
786
|
|
|
|
|
|
|
} |
787
|
|
|
|
|
|
|
|
788
|
|
|
|
|
|
|
=pod |
789
|
|
|
|
|
|
|
|
790
|
|
|
|
|
|
|
=head2 C |
791
|
|
|
|
|
|
|
|
792
|
|
|
|
|
|
|
Returns the error message from the last call, if there was one, e.g., |
793
|
|
|
|
|
|
|
|
794
|
|
|
|
|
|
|
my $data = JSON::DWIW->from_json($json_str) |
795
|
|
|
|
|
|
|
or die "JSON error: " . JSON::DWIW->get_error_string; |
796
|
|
|
|
|
|
|
|
797
|
|
|
|
|
|
|
my $data = $json_obj->from_json($json_str) |
798
|
|
|
|
|
|
|
or die "JSON error: " . $json_obj->get_error_string; |
799
|
|
|
|
|
|
|
|
800
|
|
|
|
|
|
|
|
801
|
|
|
|
|
|
|
Aliases: get_err_str(), errstr() |
802
|
|
|
|
|
|
|
|
803
|
|
|
|
|
|
|
=cut |
804
|
|
|
|
|
|
|
sub get_error_string { |
805
|
53
|
|
|
53
|
1
|
17985
|
my $self = shift; |
806
|
|
|
|
|
|
|
|
807
|
53
|
100
|
|
|
|
142
|
if (ref($self)) { |
808
|
2
|
|
|
|
|
13
|
return $self->{last_error}; |
809
|
|
|
|
|
|
|
} |
810
|
|
|
|
|
|
|
|
811
|
51
|
|
|
|
|
183
|
return $JSON::DWIW::LastError; |
812
|
|
|
|
|
|
|
} |
813
|
|
|
|
|
|
|
*get_err_str = \&get_error_string; |
814
|
|
|
|
|
|
|
*errstr = \&get_error_string; |
815
|
|
|
|
|
|
|
|
816
|
|
|
|
|
|
|
=pod |
817
|
|
|
|
|
|
|
|
818
|
|
|
|
|
|
|
=head2 C |
819
|
|
|
|
|
|
|
|
820
|
|
|
|
|
|
|
Returns the error details from the last call, in a hash ref, e.g., |
821
|
|
|
|
|
|
|
|
822
|
|
|
|
|
|
|
$error_data = { |
823
|
|
|
|
|
|
|
'byte' => 23, |
824
|
|
|
|
|
|
|
'byte_col' => 23, |
825
|
|
|
|
|
|
|
'col' => 22, |
826
|
|
|
|
|
|
|
'char' => 22, |
827
|
|
|
|
|
|
|
'version' => '0.15a', |
828
|
|
|
|
|
|
|
'line' => 1 |
829
|
|
|
|
|
|
|
}; |
830
|
|
|
|
|
|
|
|
831
|
|
|
|
|
|
|
This is really only useful when decoding JSON. |
832
|
|
|
|
|
|
|
|
833
|
|
|
|
|
|
|
Aliases: get_error(), error() |
834
|
|
|
|
|
|
|
|
835
|
|
|
|
|
|
|
=cut |
836
|
|
|
|
|
|
|
sub get_error_data { |
837
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
838
|
|
|
|
|
|
|
|
839
|
0
|
0
|
|
|
|
0
|
if (ref($self)) { |
840
|
0
|
|
|
|
|
0
|
return $self->{last_error_data}; |
841
|
|
|
|
|
|
|
} |
842
|
|
|
|
|
|
|
|
843
|
0
|
|
|
|
|
0
|
return $JSON::DWIW::LastErrorData; |
844
|
|
|
|
|
|
|
} |
845
|
|
|
|
|
|
|
*get_error = \&get_error_data; |
846
|
|
|
|
|
|
|
*error = \&get_error_data; |
847
|
|
|
|
|
|
|
|
848
|
|
|
|
|
|
|
=pod |
849
|
|
|
|
|
|
|
|
850
|
|
|
|
|
|
|
=head2 C |
851
|
|
|
|
|
|
|
|
852
|
|
|
|
|
|
|
Returns statistics from the last method called to encode or |
853
|
|
|
|
|
|
|
decode. E.g., for an encoding (C or C), |
854
|
|
|
|
|
|
|
|
855
|
|
|
|
|
|
|
$stats = { |
856
|
|
|
|
|
|
|
'bytes' => 78, |
857
|
|
|
|
|
|
|
'nulls' => 1, |
858
|
|
|
|
|
|
|
'max_string_bytes' => 5, |
859
|
|
|
|
|
|
|
'max_depth' => 2, |
860
|
|
|
|
|
|
|
'arrays' => 1, |
861
|
|
|
|
|
|
|
'numbers' => 6, |
862
|
|
|
|
|
|
|
'lines' => 1, |
863
|
|
|
|
|
|
|
'max_string_chars' => 5, |
864
|
|
|
|
|
|
|
'strings' => 6, |
865
|
|
|
|
|
|
|
'bools' => 1, |
866
|
|
|
|
|
|
|
'chars' => 78, |
867
|
|
|
|
|
|
|
'hashes' => 1 |
868
|
|
|
|
|
|
|
}; |
869
|
|
|
|
|
|
|
|
870
|
|
|
|
|
|
|
=cut |
871
|
|
|
|
|
|
|
sub get_stats { |
872
|
11
|
|
|
11
|
1
|
5237
|
my $self = shift; |
873
|
11
|
50
|
|
|
|
43
|
if (ref($self)) { |
874
|
0
|
|
|
|
|
0
|
return $self->{last_stats}; |
875
|
|
|
|
|
|
|
} |
876
|
|
|
|
|
|
|
|
877
|
11
|
|
|
|
|
34
|
return $JSON::DWIW::Last_Stats; |
878
|
|
|
|
|
|
|
} |
879
|
|
|
|
|
|
|
*stats = \&get_stats; |
880
|
|
|
|
|
|
|
|
881
|
|
|
|
|
|
|
|
882
|
|
|
|
|
|
|
=pod |
883
|
|
|
|
|
|
|
|
884
|
|
|
|
|
|
|
=head2 C |
885
|
|
|
|
|
|
|
|
886
|
|
|
|
|
|
|
Returns an object that will get output as a true value when encoding to JSON. |
887
|
|
|
|
|
|
|
|
888
|
|
|
|
|
|
|
=cut |
889
|
|
|
|
|
|
|
|
890
|
|
|
|
|
|
|
sub true { |
891
|
1
|
|
|
1
|
1
|
184
|
return JSON::DWIW::Boolean->true; |
892
|
|
|
|
|
|
|
} |
893
|
|
|
|
|
|
|
|
894
|
|
|
|
|
|
|
=pod |
895
|
|
|
|
|
|
|
|
896
|
|
|
|
|
|
|
=head2 C |
897
|
|
|
|
|
|
|
|
898
|
|
|
|
|
|
|
Returns an object that will get output as a false value when encoding to JSON. |
899
|
|
|
|
|
|
|
|
900
|
|
|
|
|
|
|
=cut |
901
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
sub false { |
903
|
1
|
|
|
1
|
1
|
174
|
return JSON::DWIW::Boolean->false; |
904
|
|
|
|
|
|
|
} |
905
|
|
|
|
|
|
|
|
906
|
|
|
|
|
|
|
sub _escape_xml_body { |
907
|
52
|
|
|
52
|
|
45
|
my ($text) = @_; |
908
|
52
|
50
|
|
|
|
83
|
return undef unless defined $text; |
909
|
|
|
|
|
|
|
|
910
|
|
|
|
|
|
|
# FIXME: benchmark this and test fully |
911
|
|
|
|
|
|
|
# $text =~ s/([&<>"'])/$Escape_Map->{$1}/eg; |
912
|
|
|
|
|
|
|
# return $text; |
913
|
|
|
|
|
|
|
|
914
|
52
|
|
|
|
|
87
|
$text =~ s/\&/\&/g; |
915
|
52
|
|
|
|
|
53
|
$text =~ s/\</g; |
916
|
52
|
|
|
|
|
56
|
$text =~ s/>/\>/g; |
917
|
|
|
|
|
|
|
|
918
|
52
|
|
|
|
|
132
|
return $text; |
919
|
|
|
|
|
|
|
} |
920
|
|
|
|
|
|
|
|
921
|
|
|
|
|
|
|
sub _escape_xml_attr { |
922
|
0
|
|
|
0
|
|
0
|
my ($text) = @_; |
923
|
0
|
0
|
|
|
|
0
|
return undef unless defined $text; |
924
|
|
|
|
|
|
|
|
925
|
|
|
|
|
|
|
# FIXME: benchmark this and test fully |
926
|
|
|
|
|
|
|
# $text =~ s/([&<>"'])/$Escape_Map->{$1}/eg; |
927
|
|
|
|
|
|
|
# return $text; |
928
|
|
|
|
|
|
|
|
929
|
0
|
|
|
|
|
0
|
$text =~ s/\&/\&/g; |
930
|
0
|
|
|
|
|
0
|
$text =~ s/\</g; |
931
|
0
|
|
|
|
|
0
|
$text =~ s/>/\>/g; |
932
|
0
|
|
|
|
|
0
|
$text =~ s/\"/\"/g; |
933
|
|
|
|
|
|
|
|
934
|
0
|
|
|
|
|
0
|
return $text; |
935
|
|
|
|
|
|
|
} |
936
|
|
|
|
|
|
|
|
937
|
|
|
|
|
|
|
sub _to_xml { |
938
|
78
|
|
|
78
|
|
98
|
my ($data, $level, $params, $parent_tag) = @_; |
939
|
|
|
|
|
|
|
|
940
|
78
|
50
|
|
|
|
122
|
return '' unless defined $data; |
941
|
|
|
|
|
|
|
|
942
|
78
|
100
|
66
|
|
|
291
|
$params = { } unless $params and UNIVERSAL::isa($params, 'HASH'); |
943
|
78
|
|
100
|
|
|
115
|
$level ||= 0; |
944
|
|
|
|
|
|
|
|
945
|
78
|
|
|
|
|
69
|
my $xml = ''; |
946
|
|
|
|
|
|
|
|
947
|
78
|
|
|
|
|
77
|
my $ref = ref($data); |
948
|
|
|
|
|
|
|
|
949
|
78
|
100
|
|
|
|
106
|
unless ($ref) { |
950
|
|
|
|
|
|
|
# string |
951
|
52
|
|
|
|
|
66
|
return _escape_xml_body($data); |
952
|
|
|
|
|
|
|
} |
953
|
|
|
|
|
|
|
|
954
|
26
|
50
|
|
|
|
43
|
my $indent = $params->{pretty} ? (' ' x $level) : ''; |
955
|
26
|
50
|
|
|
|
36
|
my $nl = $params->{pretty} ? "\n" : ''; |
956
|
26
|
50
|
33
|
|
|
54
|
my $start = ($params->{pretty} and $level) ? "\n" : ''; |
957
|
26
|
50
|
33
|
|
|
47
|
my $end = ($params->{pretty} and $level >= 2) ? (' ' x ($level - 1)) : ''; |
958
|
26
|
|
|
|
|
23
|
my $first = 1; |
959
|
|
|
|
|
|
|
|
960
|
26
|
100
|
|
|
|
46
|
if ($ref eq 'ARRAY') { |
|
|
50
|
|
|
|
|
|
961
|
10
|
|
|
|
|
19
|
foreach my $e (@$data) { |
962
|
31
|
|
|
|
|
54
|
$xml .= "$start$indent<$parent_tag>"; |
963
|
31
|
|
|
|
|
62
|
$xml .= _to_xml($e, $level + 1, $params, $parent_tag); |
964
|
31
|
|
|
|
|
70
|
$xml .= "$parent_tag>$nl$end"; |
965
|
|
|
|
|
|
|
} |
966
|
|
|
|
|
|
|
continue { |
967
|
31
|
|
|
|
|
50
|
$first = 0; |
968
|
|
|
|
|
|
|
} |
969
|
|
|
|
|
|
|
|
970
|
10
|
|
|
|
|
24
|
return $xml; |
971
|
|
|
|
|
|
|
} |
972
|
|
|
|
|
|
|
elsif ($ref eq 'HASH') { |
973
|
16
|
|
|
|
|
55
|
foreach my $k (sort keys %$data) { |
974
|
42
|
100
|
|
|
|
75
|
$start = '' unless $first; |
975
|
42
|
|
|
|
|
104
|
(my $tag = $k) =~ s/[^\w-]/_/g; |
976
|
42
|
|
|
|
|
78
|
my $this_ref = ref($data->{$k}); |
977
|
42
|
100
|
100
|
|
|
107
|
if ($this_ref and $this_ref eq 'ARRAY') { |
978
|
10
|
|
|
|
|
22
|
$xml .= _to_xml($data->{$k}, $level, $params, $tag); |
979
|
10
|
|
|
|
|
14
|
next; |
980
|
|
|
|
|
|
|
} |
981
|
|
|
|
|
|
|
|
982
|
32
|
|
|
|
|
54
|
$xml .= "$start$indent<$tag>"; |
983
|
32
|
|
|
|
|
74
|
$xml .= _to_xml($data->{$k}, $level + 1, $params, $tag); |
984
|
32
|
|
|
|
|
71
|
$xml .= "$tag>$nl$end"; |
985
|
|
|
|
|
|
|
} |
986
|
|
|
|
|
|
|
continue { |
987
|
42
|
|
|
|
|
65
|
$first = 0; |
988
|
|
|
|
|
|
|
} |
989
|
|
|
|
|
|
|
|
990
|
16
|
|
|
|
|
61
|
return $xml; |
991
|
|
|
|
|
|
|
} |
992
|
|
|
|
|
|
|
else { |
993
|
|
|
|
|
|
|
# make sure objects are stringified, e.g., Math::BigInt |
994
|
0
|
|
|
|
|
0
|
return _escape_xml_body($data . ''); |
995
|
|
|
|
|
|
|
} |
996
|
|
|
|
|
|
|
|
997
|
0
|
|
|
|
|
0
|
return $xml; |
998
|
|
|
|
|
|
|
} |
999
|
|
|
|
|
|
|
|
1000
|
|
|
|
|
|
|
sub _data_to_xml { |
1001
|
5
|
|
|
5
|
|
7
|
my ($data, $params) = @_; |
1002
|
|
|
|
|
|
|
|
1003
|
5
|
|
|
|
|
10
|
return _to_xml($data, 0, $params); |
1004
|
|
|
|
|
|
|
} |
1005
|
|
|
|
|
|
|
|
1006
|
|
|
|
|
|
|
|
1007
|
|
|
|
|
|
|
=pod |
1008
|
|
|
|
|
|
|
|
1009
|
|
|
|
|
|
|
=head2 C |
1010
|
|
|
|
|
|
|
|
1011
|
|
|
|
|
|
|
This function (not a method) converts the given JSON to XML. |
1012
|
|
|
|
|
|
|
Hash/object keys become tag names. Arrays that are hash values |
1013
|
|
|
|
|
|
|
are output as multiple tags with the hash key as the tag name. |
1014
|
|
|
|
|
|
|
|
1015
|
|
|
|
|
|
|
Any characters in hash keys not in C<[\w-]> (i.e., letters, numbers, |
1016
|
|
|
|
|
|
|
underscore, or dash), get converted to underscore ("_") when |
1017
|
|
|
|
|
|
|
output as XML tags. |
1018
|
|
|
|
|
|
|
|
1019
|
|
|
|
|
|
|
Valid parameters in C<\%params> are the same as for passing |
1020
|
|
|
|
|
|
|
to C or C, plus the C option, which |
1021
|
|
|
|
|
|
|
will add newlines and indentation to the XML to make it more |
1022
|
|
|
|
|
|
|
human-readable. |
1023
|
|
|
|
|
|
|
|
1024
|
|
|
|
|
|
|
=cut |
1025
|
|
|
|
|
|
|
sub json_to_xml { |
1026
|
5
|
|
|
5
|
1
|
1100
|
my ($json, $params) = @_; |
1027
|
|
|
|
|
|
|
|
1028
|
5
|
|
|
|
|
5
|
my $data; |
1029
|
5
|
50
|
|
|
|
10
|
if ($params) { |
1030
|
0
|
|
|
|
|
0
|
$data = JSON::DWIW::deserialize($json, $params); |
1031
|
|
|
|
|
|
|
} |
1032
|
|
|
|
|
|
|
else { |
1033
|
5
|
|
|
|
|
287
|
$data = JSON::DWIW::deserialize($json); |
1034
|
|
|
|
|
|
|
} |
1035
|
|
|
|
|
|
|
|
1036
|
5
|
|
|
|
|
17
|
my $ref = ref($data); |
1037
|
5
|
50
|
33
|
|
|
24
|
if ($ref and $ref eq 'ARRAY') { |
1038
|
0
|
|
|
|
|
0
|
warn "top level of data must be an object/hash ref in json_to_xml() call"; |
1039
|
0
|
|
|
|
|
0
|
return undef; |
1040
|
|
|
|
|
|
|
} |
1041
|
|
|
|
|
|
|
|
1042
|
5
|
|
|
|
|
14
|
return _data_to_xml($data, $params); |
1043
|
|
|
|
|
|
|
} |
1044
|
|
|
|
|
|
|
|
1045
|
|
|
|
|
|
|
sub jsonml_to_xml { |
1046
|
0
|
|
|
0
|
0
|
|
my ($jsonml) = @_; |
1047
|
|
|
|
|
|
|
|
1048
|
0
|
|
|
|
|
|
my $elements = JSON::DWIW::deserialize($jsonml); |
1049
|
0
|
0
|
|
|
|
|
return undef unless defined $elements; |
1050
|
|
|
|
|
|
|
|
1051
|
0
|
|
|
|
|
|
return _jsonml_xml($elements); |
1052
|
|
|
|
|
|
|
} |
1053
|
|
|
|
|
|
|
|
1054
|
|
|
|
|
|
|
sub _jsonml_xml { |
1055
|
0
|
|
|
0
|
|
|
my ($elements) = @_; |
1056
|
|
|
|
|
|
|
|
1057
|
0
|
0
|
|
|
|
|
unless (ref($elements)) { |
1058
|
|
|
|
|
|
|
# string |
1059
|
0
|
|
|
|
|
|
return _escape_xml_body($elements); |
1060
|
|
|
|
|
|
|
} |
1061
|
|
|
|
|
|
|
|
1062
|
0
|
|
|
|
|
|
my $name = $elements->[0]; |
1063
|
0
|
|
|
|
|
|
my $attrs = $elements->[1]; |
1064
|
0
|
|
|
|
|
|
my $attr_str = ''; |
1065
|
|
|
|
|
|
|
|
1066
|
0
|
|
|
|
|
|
my @rest; |
1067
|
0
|
0
|
0
|
|
|
|
if (defined $attrs and UNIVERSAL::isa($attrs, 'HASH')) { |
1068
|
0
|
|
|
|
|
|
my @keys = sort keys %$attrs; |
1069
|
0
|
|
|
|
|
|
my @pairs = map { qq{$_="} . _escape_xml_attr($attrs->{$_}) . qq{"} } @keys; |
|
0
|
|
|
|
|
|
|
1070
|
0
|
|
|
|
|
|
$attr_str = ' ' . join(' ', @pairs); |
1071
|
0
|
|
|
|
|
|
@rest = @$elements[2 .. $#$elements]; |
1072
|
|
|
|
|
|
|
} |
1073
|
|
|
|
|
|
|
else { |
1074
|
0
|
|
|
|
|
|
$attrs = undef; |
1075
|
0
|
|
|
|
|
|
@rest = @$elements[1 .. $#$elements]; |
1076
|
|
|
|
|
|
|
} |
1077
|
|
|
|
|
|
|
|
1078
|
0
|
|
|
|
|
|
my $xml = "<$name$attr_str"; |
1079
|
|
|
|
|
|
|
|
1080
|
0
|
0
|
|
|
|
|
if (@rest) { |
1081
|
0
|
|
|
|
|
|
$xml .= '>'; |
1082
|
0
|
|
|
|
|
|
foreach my $e (@rest) { |
1083
|
0
|
|
|
|
|
|
$xml .= _jsonml_xml($e); |
1084
|
|
|
|
|
|
|
} |
1085
|
0
|
|
|
|
|
|
$xml .= "$name>"; |
1086
|
|
|
|
|
|
|
} |
1087
|
|
|
|
|
|
|
else { |
1088
|
0
|
|
|
|
|
|
$xml .= '/>'; |
1089
|
|
|
|
|
|
|
} |
1090
|
|
|
|
|
|
|
|
1091
|
0
|
|
|
|
|
|
return $xml; |
1092
|
|
|
|
|
|
|
} |
1093
|
|
|
|
|
|
|
|
1094
|
|
|
|
|
|
|
# used from XS code to sort keys in Perl < 5.8.0 where we don't have |
1095
|
|
|
|
|
|
|
# access to sortsv() from XS |
1096
|
|
|
|
|
|
|
sub _sort_keys { |
1097
|
0
|
|
|
0
|
|
|
return [ sort keys %{ $_[0] } ] |
|
0
|
|
|
|
|
|
|
1098
|
|
|
|
|
|
|
} |
1099
|
|
|
|
|
|
|
|
1100
|
|
|
|
|
|
|
|
1101
|
|
|
|
|
|
|
=pod |
1102
|
|
|
|
|
|
|
|
1103
|
|
|
|
|
|
|
=head1 Utilities |
1104
|
|
|
|
|
|
|
|
1105
|
|
|
|
|
|
|
Following are some methods I use for debugging and testing. |
1106
|
|
|
|
|
|
|
|
1107
|
|
|
|
|
|
|
=head2 C |
1108
|
|
|
|
|
|
|
|
1109
|
|
|
|
|
|
|
Returns true if the given string is flagged as utf-8. |
1110
|
|
|
|
|
|
|
|
1111
|
|
|
|
|
|
|
=head2 C |
1112
|
|
|
|
|
|
|
|
1113
|
|
|
|
|
|
|
Flags the given string as utf-8. |
1114
|
|
|
|
|
|
|
|
1115
|
|
|
|
|
|
|
=head2 C |
1116
|
|
|
|
|
|
|
|
1117
|
|
|
|
|
|
|
Clears the flag that tells Perl the string is utf-8. |
1118
|
|
|
|
|
|
|
|
1119
|
|
|
|
|
|
|
=head2 C |
1120
|
|
|
|
|
|
|
|
1121
|
|
|
|
|
|
|
Returns true if the given string is valid utf-8 (regardless of the flag). |
1122
|
|
|
|
|
|
|
|
1123
|
|
|
|
|
|
|
=head2 C |
1124
|
|
|
|
|
|
|
|
1125
|
|
|
|
|
|
|
Converts the string to utf-8, assuming it is latin1. This effects $str itself in place, but also returns $str. |
1126
|
|
|
|
|
|
|
|
1127
|
|
|
|
|
|
|
=head2 C |
1128
|
|
|
|
|
|
|
|
1129
|
|
|
|
|
|
|
Returns a utf8 string containing the byte sequence for the given code point. |
1130
|
|
|
|
|
|
|
|
1131
|
|
|
|
|
|
|
=head2 C |
1132
|
|
|
|
|
|
|
|
1133
|
|
|
|
|
|
|
Returns a string representing the byte sequence for $cp encoding in utf-8. E.g., |
1134
|
|
|
|
|
|
|
|
1135
|
|
|
|
|
|
|
my $hex_bytes = JSON::DWIW->code_point_to_hex_bytes(0xe9); |
1136
|
|
|
|
|
|
|
print "$hex_bytes\n"; # \xc3\xa9 |
1137
|
|
|
|
|
|
|
|
1138
|
|
|
|
|
|
|
=head2 C |
1139
|
|
|
|
|
|
|
|
1140
|
|
|
|
|
|
|
Returns a reference to an array of code points from the given string, assuming the string is encoded in utf-8. |
1141
|
|
|
|
|
|
|
|
1142
|
|
|
|
|
|
|
=head2 C |
1143
|
|
|
|
|
|
|
|
1144
|
|
|
|
|
|
|
Dumps the internal structure of the given scalar. |
1145
|
|
|
|
|
|
|
|
1146
|
|
|
|
|
|
|
=head1 BENCHMARKS |
1147
|
|
|
|
|
|
|
|
1148
|
|
|
|
|
|
|
Need new benchmarks here. |
1149
|
|
|
|
|
|
|
|
1150
|
|
|
|
|
|
|
=head1 DEPENDENCIES |
1151
|
|
|
|
|
|
|
|
1152
|
|
|
|
|
|
|
Perl 5.6 or later |
1153
|
|
|
|
|
|
|
|
1154
|
|
|
|
|
|
|
=head1 BUGS/LIMITATIONS |
1155
|
|
|
|
|
|
|
|
1156
|
|
|
|
|
|
|
If you find a bug, please file a tracker request at |
1157
|
|
|
|
|
|
|
L. |
1158
|
|
|
|
|
|
|
|
1159
|
|
|
|
|
|
|
When decoding a JSON string, it is a assumed to be utf-8 encoded. |
1160
|
|
|
|
|
|
|
The module should detect whether the input is utf-8, utf-16, or |
1161
|
|
|
|
|
|
|
utf-32. |
1162
|
|
|
|
|
|
|
|
1163
|
|
|
|
|
|
|
=head1 AUTHOR |
1164
|
|
|
|
|
|
|
|
1165
|
|
|
|
|
|
|
Don Owens |
1166
|
|
|
|
|
|
|
|
1167
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS |
1168
|
|
|
|
|
|
|
|
1169
|
|
|
|
|
|
|
Thanks to Asher Blum for help with testing. |
1170
|
|
|
|
|
|
|
|
1171
|
|
|
|
|
|
|
Thanks to Nigel Bowden for helping with compilation on Windows. |
1172
|
|
|
|
|
|
|
|
1173
|
|
|
|
|
|
|
Thanks to Robert Peters for discovering and tracking down the source of a number parsing bug. |
1174
|
|
|
|
|
|
|
|
1175
|
|
|
|
|
|
|
Thanks to Mark Phillips for helping with a bug under Solaris on Sparc. |
1176
|
|
|
|
|
|
|
|
1177
|
|
|
|
|
|
|
Thanks to Josh for helping debug [rt.cpan.org #47344]. |
1178
|
|
|
|
|
|
|
|
1179
|
|
|
|
|
|
|
=head1 LICENSE AND COPYRIGHT |
1180
|
|
|
|
|
|
|
|
1181
|
|
|
|
|
|
|
Copyright (c) 2007-2010 Don Owens . All rights reserved. |
1182
|
|
|
|
|
|
|
|
1183
|
|
|
|
|
|
|
This is free software; you can redistribute it and/or modify it |
1184
|
|
|
|
|
|
|
under the same terms as Perl itself. See perlartistic. |
1185
|
|
|
|
|
|
|
|
1186
|
|
|
|
|
|
|
This program is distributed in the hope that it will be |
1187
|
|
|
|
|
|
|
useful, but WITHOUT ANY WARRANTY; without even the implied |
1188
|
|
|
|
|
|
|
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
1189
|
|
|
|
|
|
|
PURPOSE. |
1190
|
|
|
|
|
|
|
|
1191
|
|
|
|
|
|
|
=head1 SEE ALSO |
1192
|
|
|
|
|
|
|
|
1193
|
|
|
|
|
|
|
=over 4 |
1194
|
|
|
|
|
|
|
|
1195
|
|
|
|
|
|
|
=item The JSON home page: L |
1196
|
|
|
|
|
|
|
|
1197
|
|
|
|
|
|
|
=item The JSON spec: L |
1198
|
|
|
|
|
|
|
|
1199
|
|
|
|
|
|
|
=item The JSON-RPC spec: L |
1200
|
|
|
|
|
|
|
|
1201
|
|
|
|
|
|
|
=item L |
1202
|
|
|
|
|
|
|
|
1203
|
|
|
|
|
|
|
=item L (included in L) |
1204
|
|
|
|
|
|
|
|
1205
|
|
|
|
|
|
|
=back |
1206
|
|
|
|
|
|
|
|
1207
|
|
|
|
|
|
|
=cut |
1208
|
|
|
|
|
|
|
|
1209
|
|
|
|
|
|
|
1; |
1210
|
|
|
|
|
|
|
|
1211
|
|
|
|
|
|
|
# Local Variables: # |
1212
|
|
|
|
|
|
|
# mode: perl # |
1213
|
|
|
|
|
|
|
# tab-width: 4 # |
1214
|
|
|
|
|
|
|
# indent-tabs-mode: nil # |
1215
|
|
|
|
|
|
|
# cperl-indent-level: 4 # |
1216
|
|
|
|
|
|
|
# perl-indent-level: 4 # |
1217
|
|
|
|
|
|
|
# End: # |
1218
|
|
|
|
|
|
|
# vim:set ai si et sta ts=4 sw=4 sts=4: |