-
Notifications
You must be signed in to change notification settings - Fork 6
/
jsonio.ado
323 lines (231 loc) · 10.1 KB
/
jsonio.ado
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
********************************************************************************
* *
* Description - *
* Program to serialize a dataset and return a JSON representation of the *
* data. *
* *
* System Requirements - *
* JRE 1.8 or Higher. *
* *
* Output - (Optional) *
* Either prints a JSON object to the Stata console or writes one to disk. *
* *
* Lines - *
* 322 *
* *
********************************************************************************
*! jsonio
*! 27APR2017
*! v 0.0.7
// Drop program from memory if it exists
cap prog drop jsonio
// Define program as an r-class program
prog def jsonio, rclass
// Set version
version 13.0
// Define input syntax
syntax anything(name=subtype id="Input/Output Type") [if] [in] , [ ///
ELEMents(passthru) noURL FILEnm(string) OBid(passthru) ///
METAprint(passthru) What(passthru) STUBname(passthru) ]
// Tokenize the first argument
gettoken cmd opts : subtype
// Make sure there aren't any issues with the macro expansion for filepaths
if `"`url'"' == "nourl" loc filenm `: subinstr loc filenm `"~"' `"`: env HOME'"''
// If command is keyvay
if `"`cmd'"' == "kv" keyval `"`filenm'"', `elements' `url'
// If the command is rowvalue orientation
else if `"`cmd'"' == "rv" rowval `"`filenm'"', `elements' `url' `obid' `stubname'
// For output need to pass the if/in conditions to the subroutine call
else jsonout `opts' `if' `in', filenm(`filenm') `obid' `metaprint' `what'
// Return local with the total number of keys
ret loc totalkeys `r(totalkeys)'
// Set the local macro that needs to be returned
ret loc thejson `"`r(thejson)'"'
// End of the program definition
end
// JSON Deserializer
prog def rowval, rclass
// Define input syntax
syntax anything(name=source id="Source of the JSON Input") [, ///
ELEMents(string) noURL OBid(integer 0) STUBname(string asis) ]
// If elements is null
if `"`elements'"' == "" loc elements ".*"
// Use default stubname if none specified
if "`stubname'" == "" loc stubname jsonvar
// Assumes data is coming from a URL unless specified otherwise
if `"`url'"' == "nourl" {
// Call Java method to import from file
javacall org.paces.Stata.Input.InJSON insheetFileToVars, ///
args(`source' "`elements'" "`obid'" "`stubname'")
} // End IF Block for files
// If it is a URL
else {
// Call Java method to import from URL
javacall org.paces.Stata.Input.InJSON insheetUrlToVars, ///
args(`source' "`elements'" "`obid'")
} // End ELSE Block for URLs
// Return local with the total number of keys
ret loc totalkeys `totalkeys'
// End subroutine
end
// JSON Deserializer
prog def keyval, rclass
// Define input syntax
syntax anything(name=source id="Source of the JSON Input") [, ///
ELEMents(string) noURL ]
// If elements is null
if `"`elements'"' == "" loc elements ".*"
// Assumes data is coming from a URL unless specified otherwise
if `"`url'"' == "nourl" {
// Call Java method to import from file
javacall org.paces.Stata.Input.InJSON insheetFile, ///
args(`source' "`elements'")
} // End IF Block for files
// If it is a URL
else {
// Call Java method to import from URL
javacall org.paces.Stata.Input.InJSON insheetUrl, args(`source' "`elements'")
} // End ELSE Block for URLs
// Return local with the total number of keys
ret loc totalkeys `totalkeys'
// End subroutine
end
// JSON Serializer
prog def jsonout, rclass
// Define syntax
syntax [varlist] [if] [in] [using/] , ///
[ FILEnm(string asis) OBid(real 0) METAprint(string asis) ///
What(string asis) COMMents YAML UQFNames SQuotes UQControl BACKSLash ///
LEADZero NONNUM DUPlicates UNDEFined UTF16 ]
// Normalize *nix home shortcut in file
if substr(`"`filenm'"', 1, 1) == "~" {
loc filenm `: subinstr loc filenm `"~"' `"`: env HOME'"', all'
}
/* Used to enable the ALLOW_COMMENTS property of
the JsonParser Java class from the Jackson API. For additional information
interested users should see:
http://fasterxml.github.io/jackson-core/javadoc/2.6/
*/
if `"`comments'"' == "" loc comments false
else loc comments true
/* Used to enable the ALLOW_YAML_COMMENTS property of the JsonParser Java
class from the Jackson API. */
if `"`yaml'"' == "" loc yaml false
else loc yaml true
/* Used to enable the ALLOW_UNQUOTED_FIELD_NAMES property of the JsonParser Java
class from the Jackson API. */
if `"`uqfnames'"' == "" loc uqfnames false
else loc uqfnames true
/* Used to enable the ALLOW_SINGLE_QUOTES property of the JsonParser Java
class from the Jackson API. */
if `"`squotes'"' == "" loc squotes false
else loc squotes true
/* Used to enable the ALLOW_UNQUOTED_CONTROL_CHARS property of the JsonParser Java
class from the Jackson API. */
if `"`uqcontrol'"' == "" loc uqcontrol false
else loc uqcontrol true
/* Used to enable the ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER property of the
JsonParser Java class from the Jackson API. */
if `"`backslash'"' == "" loc backslash false
else loc backslash true
/* Used to enable the ALLOW_NUMERIC_LEADING_ZEROS property of the JsonParser Java
class from the Jackson API. */
if `"`leadzero'"' == "" loc leadzero false
else loc leadzero true
/* Used to enable the ALLOW_NON_NUMERIC_NUMBERS property of the JsonParser Java
class from the Jackson API. */
if `"`nonnum'"' == "" loc nonnum false
else loc nonnum true
/* Used to enable the STRICT_DUPLICATE_DETECTION property of the JsonParser Java
class from the Jackson API. */
if `"`duplicates'"' == "" loc duplicates false
else loc duplicates true
/* Used to enable the IGNORE_UNDEFINED property of the JsonParser Java
class from the Jackson API. */
if `"`undefined'"' == "" loc undefined false
else loc undefined true
// Gets maximum length of a macro for the user
loc maxlen `= `c(maxvar)' * 129'
// Set local macro with the file name
loc filename `"`c(filename)'"'
// Clean up file path using tilde shortcut
loc filenm `: subinstr loc filenm `"~"' `"`: env HOME'"''
// Check for aguments defining what to convert
if inlist(proper("`what'"), "Record", "Data", "All") & "`metaprint'" == "" {
// Make value proper cased
loc what = proper("`what'")
} // End IF Block for what argument
// If All arguments are missing
else if "`what'" == "" & "`metaprint'" == "" {
// Print message to Stata console
di as res "No arguments provided to define what to serialize." _n ///
"Will serialize entire dataset by default."
// Set the what macro to Data
loc what Data
} // End ELSE IF Block for options to define what to serialize
// Preserve the data
preserve
// Check for using option
if `"`using'"' != "" {
// Load the specified file
qui: use `"`using'"', clear
} // End IF Block to load data from using
// Check for metadata argument
if inlist(`"`metaprint'`filenm'"', "varlabels", "varnames", "vallabs", ///
"labelnames") {
// Call java method to print metadata
javacall org.paces.Stata.JSON.StataMetaToJSON metaToJSON ///
`varlist' `if' `in', args(`utf16')
} // End IF Block for printing metadata to JSON
// For non-metadata based calls
else {
// For non metadata cases
if "`what'" == "Data" & "`filenm'" != "" {
// Call java method to write JSON object to disk
javacall org.paces.Stata.JSON.StataJSON printDataToFile ///
`varlist' `if' `in'
} // End if block for printing data to JSON
// Call to print dataset to Stata console
else if "`what'" == "Data" & "`filenm'" == "" {
// Call java method to write JSON object to the Stata console
javacall org.paces.Stata.JSON.StataJSON printData `varlist' ///
`if' `in'
} // End ELSEIF Block to print dataset to Stata console
// Call to write individual record to file
else if "`what'" == "Record" & "`filenm'" != "" {
// Call java method to write individual record to disk
javacall org.paces.Stata.JSON.StataJSON printRecordToFile ///
`varlist' `if' `in'
} // End ELSEIF Block for writing individual record to disk
// Option to print individual record to the screen
else if "`what'" == "Record" & "`filenm'" == "" {
// Call java method to print record to the Stata console
javacall org.paces.Stata.JSON.StataJSON printRecord ///
`varlist' `if' `in'
} // End ELSEIF Block to print JSON record to Stata console
// Option to print everything to the console
else if "`what'" == "All" & "`filenm'" == "" {
// Call java method to print everything to the Stata console
javacall org.paces.Stata.JSON.StataJSON printAll `varlist' ///
`if' `in'
} // End ELSEIF Block to print JSON data/metadata to Stata console
// Option to write all data to file on the disk
else {
// Call java method to print everything to the Stata console
javacall org.paces.Stata.JSON.StataJSON printAllToFile ///
`varlist' `if' `in'
} // End ELSE Block to print JSON data/metadata to disk
} // End ELSE Block for data-based function calls
// Put default error message in the macro
if `"`thejson'"' == "" ret loc thejson "JSON Object Too Large for Macro."
// Set the local macro that needs to be returned
else ret loc thejson `"`thejson'"'
// Restore data to that originally in memory
restore
// Set all of the local macros to null
loc filenm
loc what
loc obid
loc metaprint
// End function definition
end