├── README.md
├── java-version
├── .classpath
├── .project
├── .settings
│ └── org.eclipse.jdt.core.prefs
├── bin
│ ├── com
│ │ └── bgw
│ │ │ ├── translator
│ │ │ ├── MessageTranslator.class
│ │ │ ├── RoyISO8583.class
│ │ │ ├── RoyISO8583Field.class
│ │ │ └── Translator.class
│ │ │ └── utility
│ │ │ ├── Encryption.class
│ │ │ └── Utility.class
│ ├── org
│ │ └── json
│ │ │ ├── CDL.class
│ │ │ ├── Cookie.class
│ │ │ ├── CookieList.class
│ │ │ ├── HTTP.class
│ │ │ ├── HTTPTokener.class
│ │ │ ├── JSONArray.class
│ │ │ ├── JSONException.class
│ │ │ ├── JSONML.class
│ │ │ ├── JSONObject$Null.class
│ │ │ ├── JSONObject.class
│ │ │ ├── JSONPointer$Builder.class
│ │ │ ├── JSONPointer.class
│ │ │ ├── JSONPointerException.class
│ │ │ ├── JSONPropertyIgnore.class
│ │ │ ├── JSONPropertyName.class
│ │ │ ├── JSONString.class
│ │ │ ├── JSONStringer.class
│ │ │ ├── JSONTokener.class
│ │ │ ├── JSONWriter.class
│ │ │ ├── Property.class
│ │ │ ├── XML$1$1.class
│ │ │ ├── XML$1.class
│ │ │ ├── XML.class
│ │ │ └── XMLTokener.class
│ └── test
│ │ └── Test.class
└── src
│ ├── com
│ └── bgw
│ │ ├── translator
│ │ ├── MessageTranslator.java
│ │ ├── RoyISO8583.java
│ │ ├── RoyISO8583Field.java
│ │ └── Translator.java
│ │ └── utility
│ │ ├── Encryption.java
│ │ └── Utility.java
│ ├── org
│ └── json
│ │ ├── CDL.java
│ │ ├── Cookie.java
│ │ ├── CookieList.java
│ │ ├── HTTP.java
│ │ ├── HTTPTokener.java
│ │ ├── JSONArray.java
│ │ ├── JSONException.java
│ │ ├── JSONML.java
│ │ ├── JSONObject.java
│ │ ├── JSONPointer.java
│ │ ├── JSONPointerException.java
│ │ ├── JSONPropertyIgnore.java
│ │ ├── JSONPropertyName.java
│ │ ├── JSONString.java
│ │ ├── JSONStringer.java
│ │ ├── JSONTokener.java
│ │ ├── JSONWriter.java
│ │ ├── Property.java
│ │ ├── XML.java
│ │ └── XMLTokener.java
│ └── test
│ └── Test.java
└── php-version
├── index.php
└── lib
├── MessageTranslator.php
└── RoyISO8583.php
/README.md:
--------------------------------------------------------------------------------
1 | # ISO8583-JSON-XML
2 | This library is used to convert messages from one format to another. The supported formats are ISO 8583, JSON, and XML.
3 |
4 | Beginner programmers often experience difficulties when parsing and building data with ISO 8583 format. Most programmers are more familiar with human readable formats such as JSON and XML. On the other hand, however, the company requires the ISO 8583 format because some or all of the partners use that format.
5 |
6 | Using this library, both senior programmers and novice programmers will be easier to build applications that use the ISO 8583 message format.
7 |
8 | You can save the configuration on file or database as string.
9 |
10 | ### Capability
11 |
12 | 1. Convert JSON to ISO 8583
13 | 2. Convert XML to ISO 8583
14 | 3. Convert ISO 8583 to JSON
15 | 4. Convert ISO 8583 to XML
16 | 5. Convert JSON to XML
17 | 6. Convert XML to JSON
18 |
19 | ### Example
20 |
21 | Script
22 |
23 | ```java
24 | package test;
25 |
26 | import java.io.IOException;
27 |
28 | import org.json.JSONArray;
29 | import org.json.JSONException;
30 | import org.json.JSONObject;
31 |
32 | import com.bgw.translator.MessageTranslator;
33 |
34 | public class Test {
35 | public static void main(String[] args) throws IOException {
36 | String configStr = "[{\"field\":\"2\",\"format\":\"%-6s\",\"variable\":\"pan\",\"options\":\"\",\"type\":\"LLVAR\",\"field_length\":\"6\"},{\"field\":\"3\",\"format\":\"%06d\",\"variable\":\"processing_code\",\"options\":\"\",\"type\":\"NUMERIC\",\"field_length\":\"6\"},{\"field\":\"4\",\"format\":\"%012d\",\"variable\":\"amount\",\"options\":\"\",\"type\":\"NUMERIC\",\"field_length\":\"12\"},{\"field\":\"7\",\"format\":\"%-10s\",\"variable\":\"transmission_date_time\",\"options\":\"\",\"type\":\"STRING\",\"field_length\":\"10\"},{\"field\":\"11\",\"format\":\"%06d\",\"variable\":\"stan\",\"options\":\"\",\"type\":\"NUMERIC\",\"field_length\":\"6\"},{\"field\":\"12\",\"format\":\"%-6s\",\"variable\":\"local_time\",\"options\":\"\",\"type\":\"STRING\",\"field_length\":\"6\"},{\"field\":\"13\",\"format\":\"%-4s\",\"variable\":\"local_date\",\"options\":\"\",\"type\":\"STRING\",\"field_length\":\"4\"},{\"field\":\"15\",\"format\":\"%-4s\",\"variable\":\"settlement_date\",\"options\":\"\",\"type\":\"STRING\",\"field_length\":\"4\"},{\"field\":\"18\",\"format\":\"%04d\",\"variable\":\"merchant_type\",\"options\":\"\",\"type\":\"NUMERIC\",\"field_length\":\"4\"},{\"field\":\"32\",\"format\":\"%-3s\",\"variable\":\"acq_institution_code\",\"options\":\"\",\"type\":\"LLVAR\",\"field_length\":\"3\"},{\"field\":\"37\",\"format\":\"%012d\",\"variable\":\"reference_number\",\"options\":\"\",\"type\":\"NUMERIC\",\"field_length\":\"12\"},{\"field\":\"41\",\"format\":\"%-8s\",\"variable\":\"card_acceptor_terminal\",\"options\":\"\",\"type\":\"STRING\",\"field_length\":\"8\"},{\"field\":\"42\",\"format\":\"%15s\",\"variable\":\"acceptor_identification_code\",\"options\":\"\",\"type\":\"STRING\",\"field_length\":\"15\"},{\"field\":\"48\",\"format\":\"%-7s%011d%012d%01d%-32s%-32s%-25s%4s%-9s\",\"variable\":\"switcher_id, meter_id, customer_id, id_selector, pln_reference_number, ba_reference_number, customer_name, tariff, ceiling\",\"options\":\"\",\"type\":\"LLLVAR\",\"field_length\":\"133\"},{\"field\":\"49\",\"format\":\"%03d\",\"variable\":\"transaction_currency_code\",\"options\":\"\",\"type\":\"NUMERIC\",\"field_length\":\"3\"}]";
37 |
38 | MessageTranslator mt = new MessageTranslator();
39 | String mti_id = "0210";
40 | String iso = "0210723A400108C1800006364235361000000000050000072751515134657351515107270728678903555232442364723376832 234822 1339876 7183712217171837122171212462348242265823582523523547223323582375872385728357823758235235KAMSHORY, MT R51350 360";
41 | String iso_new = "";
42 | String xml = "";
43 | JSONArray config = new JSONArray();
44 | JSONObject json = new JSONObject();
45 |
46 |
47 | try
48 | {
49 | config = new JSONArray(configStr);
50 | json = mt.parseISO8583(iso, config);
51 | iso_new = new String(mt.buildISO8583(json, config, mti_id));
52 | xml = mt.buildXML(json, "data");
53 |
54 | System.out.println("Demonstration of conversion of ISO 8583 - JSON - XML");
55 | System.out.println("Config : ");
56 | System.out.println(config.toString());
57 | System.out.println("=============================================================");
58 |
59 | System.out.println("Original ISO 8583 : ");
60 | System.out.println("'"+iso+"'");
61 | System.out.println("Convert ISO to JSON");
62 | System.out.println("JSON : ");
63 | System.out.println(json.toString());
64 | System.out.println("=============================================================");
65 |
66 | System.out.println("Now, convert JSON to new ISO");
67 | System.out.println("New ISO 8583 : ");
68 | System.out.println("'"+iso_new+"'");
69 | System.out.println("=============================================================");
70 |
71 | System.out.println("Now, convert JSON to XML");
72 | System.out.println("XML : ");
73 | System.out.println(xml);
74 | System.out.println("=============================================================");
75 |
76 | }
77 | catch (JSONException e)
78 | {
79 | e.printStackTrace();
80 | }
81 | }
82 | }
83 | ```
84 |
85 | Output
86 |
87 | ```
88 | Demonstration of conversion of ISO 8583 - JSON - XML
89 | Config :
90 | [{"field":"2","format":"%-6s","variable":"pan","options":"","field_length":"6","type":"LLVAR"},{"field":"3","format":"%06d","variable":"processing_code","options":"","field_length":"6","type":"NUMERIC"},{"field":"4","format":"%012d","variable":"amount","options":"","field_length":"12","type":"NUMERIC"},{"field":"7","format":"%-10s","variable":"transmission_date_time","options":"","field_length":"10","type":"STRING"},{"field":"11","format":"%06d","variable":"stan","options":"","field_length":"6","type":"NUMERIC"},{"field":"12","format":"%-6s","variable":"local_time","options":"","field_length":"6","type":"STRING"},{"field":"13","format":"%-4s","variable":"local_date","options":"","field_length":"4","type":"STRING"},{"field":"15","format":"%-4s","variable":"settlement_date","options":"","field_length":"4","type":"STRING"},{"field":"18","format":"%04d","variable":"merchant_type","options":"","field_length":"4","type":"NUMERIC"},{"field":"32","format":"%-3s","variable":"acq_institution_code","options":"","field_length":"3","type":"LLVAR"},{"field":"37","format":"%012d","variable":"reference_number","options":"","field_length":"12","type":"NUMERIC"},{"field":"41","format":"%-8s","variable":"card_acceptor_terminal","options":"","field_length":"8","type":"STRING"},{"field":"42","format":"%15s","variable":"acceptor_identification_code","options":"","field_length":"15","type":"STRING"},{"field":"48","format":"%-7s%011d%012d%01d%-32s%-32s%-25s%4s%-9s","variable":"switcher_id, meter_id, customer_id, id_selector, pln_reference_number, ba_reference_number, customer_name, tariff, ceiling","options":"","field_length":"133","type":"LLLVAR"},{"field":"49","format":"%03d","variable":"transaction_currency_code","options":"","field_length":"3","type":"NUMERIC"}]
91 | =============================================================
92 | Original ISO 8583 :
93 | '0210723A400108C1800006364235361000000000050000072751515134657351515107270728678903555232442364723376832 234822 1339876 7183712217171837122171212462348242265823582523523547223323582375872385728357823758235235KAMSHORY, MT R51350 360'
94 | Convert ISO to JSON
95 | JSON :
96 | {"ceiling":"1350 ","amount":"50000","settlement_date":"0728","switcher_id":"9876 ","ba_reference_number":"23582375872385728357823758235235","processing_code":"361000","transaction_currency_code":"360","id_selector":"1","reference_number":"232442364723","local_date":"0727","pln_reference_number":"24623482422658235825235235472233","local_time":"515151","transmission_date_time":"0727515151","stan":"346573","acq_institution_code":"555","card_acceptor_terminal":"376832 ","tariff":" R5","acceptor_identification_code":"234822 ","customer_name":"KAMSHORY, MT ","pan":"364235","customer_id":"718371221712","meter_id":"71837122171","merchant_type":"6789"}
97 | =============================================================
98 | Now, convert JSON to new ISO
99 | New ISO 8583 :
100 | '0210723A400108C1800006364235361000000000050000072751515134657351515107270728678903555232442364723376832 234822 1339876 7183712217171837122171212462348242265823582523523547223323582375872385728357823758235235KAMSHORY, MT R51350 360'
101 | =============================================================
102 | Now, convert JSON to XML
103 | XML :
104 |
105 |
33 | * Each row of text represents a row in a table or a data record. Each row 34 | * ends with a NEWLINE character. Each row contains one or more values. 35 | * Values are separated by commas. A value can contain any character except 36 | * for comma, unless is is wrapped in single quotes or double quotes. 37 | *
38 | * The first row usually contains the names of the columns. 39 | *
40 | * A comma delimited list can be converted into a JSONArray of JSONObjects.
41 | * The names for the elements in the JSONObjects can be taken from the names
42 | * in the first row.
43 | * @author JSON.org
44 | * @version 2016-05-01
45 | */
46 | public class CDL {
47 |
48 | /**
49 | * Get the next value. The value can be wrapped in quotes. The value can
50 | * be empty.
51 | * @param x A JSONTokener of the source text.
52 | * @return The value string, or null if empty.
53 | * @throws JSONException if the quoted string is badly formed.
54 | */
55 | private static String getValue(JSONTokener x) throws JSONException {
56 | char c;
57 | char q;
58 | StringBuffer sb;
59 | do {
60 | c = x.next();
61 | } while (c == ' ' || c == '\t');
62 | switch (c) {
63 | case 0:
64 | return null;
65 | case '"':
66 | case '\'':
67 | q = c;
68 | sb = new StringBuffer();
69 | for (;;) {
70 | c = x.next();
71 | if (c == q) {
72 | //Handle escaped double-quote
73 | char nextC = x.next();
74 | if(nextC != '\"') {
75 | // if our quote was the end of the file, don't step
76 | if(nextC > 0) {
77 | x.back();
78 | }
79 | break;
80 | }
81 | }
82 | if (c == 0 || c == '\n' || c == '\r') {
83 | throw x.syntaxError("Missing close quote '" + q + "'.");
84 | }
85 | sb.append(c);
86 | }
87 | return sb.toString();
88 | case ',':
89 | x.back();
90 | return "";
91 | default:
92 | x.back();
93 | return x.nextTo(',');
94 | }
95 | }
96 |
97 | /**
98 | * Produce a JSONArray of strings from a row of comma delimited values.
99 | * @param x A JSONTokener of the source text.
100 | * @return A JSONArray of strings.
101 | * @throws JSONException
102 | */
103 | public static JSONArray rowToJSONArray(JSONTokener x) throws JSONException {
104 | JSONArray ja = new JSONArray();
105 | for (;;) {
106 | String value = getValue(x);
107 | char c = x.next();
108 | if (value == null ||
109 | (ja.length() == 0 && value.length() == 0 && c != ',')) {
110 | return null;
111 | }
112 | ja.put(value);
113 | for (;;) {
114 | if (c == ',') {
115 | break;
116 | }
117 | if (c != ' ') {
118 | if (c == '\n' || c == '\r' || c == 0) {
119 | return ja;
120 | }
121 | throw x.syntaxError("Bad character '" + c + "' (" +
122 | (int)c + ").");
123 | }
124 | c = x.next();
125 | }
126 | }
127 | }
128 |
129 | /**
130 | * Produce a JSONObject from a row of comma delimited text, using a
131 | * parallel JSONArray of strings to provides the names of the elements.
132 | * @param names A JSONArray of names. This is commonly obtained from the
133 | * first row of a comma delimited text file using the rowToJSONArray
134 | * method.
135 | * @param x A JSONTokener of the source text.
136 | * @return A JSONObject combining the names and values.
137 | * @throws JSONException
138 | */
139 | public static JSONObject rowToJSONObject(JSONArray names, JSONTokener x)
140 | throws JSONException {
141 | JSONArray ja = rowToJSONArray(x);
142 | return ja != null ? ja.toJSONObject(names) : null;
143 | }
144 |
145 | /**
146 | * Produce a comma delimited text row from a JSONArray. Values containing
147 | * the comma character will be quoted. Troublesome characters may be
148 | * removed.
149 | * @param ja A JSONArray of strings.
150 | * @return A string ending in NEWLINE.
151 | */
152 | public static String rowToString(JSONArray ja) {
153 | StringBuilder sb = new StringBuilder();
154 | for (int i = 0; i < ja.length(); i += 1) {
155 | if (i > 0) {
156 | sb.append(',');
157 | }
158 | Object object = ja.opt(i);
159 | if (object != null) {
160 | String string = object.toString();
161 | if (string.length() > 0 && (string.indexOf(',') >= 0 ||
162 | string.indexOf('\n') >= 0 || string.indexOf('\r') >= 0 ||
163 | string.indexOf(0) >= 0 || string.charAt(0) == '"')) {
164 | sb.append('"');
165 | int length = string.length();
166 | for (int j = 0; j < length; j += 1) {
167 | char c = string.charAt(j);
168 | if (c >= ' ' && c != '"') {
169 | sb.append(c);
170 | }
171 | }
172 | sb.append('"');
173 | } else {
174 | sb.append(string);
175 | }
176 | }
177 | }
178 | sb.append('\n');
179 | return sb.toString();
180 | }
181 |
182 | /**
183 | * Produce a JSONArray of JSONObjects from a comma delimited text string,
184 | * using the first row as a source of names.
185 | * @param string The comma delimited text.
186 | * @return A JSONArray of JSONObjects.
187 | * @throws JSONException
188 | */
189 | public static JSONArray toJSONArray(String string) throws JSONException {
190 | return toJSONArray(new JSONTokener(string));
191 | }
192 |
193 | /**
194 | * Produce a JSONArray of JSONObjects from a comma delimited text string,
195 | * using the first row as a source of names.
196 | * @param x The JSONTokener containing the comma delimited text.
197 | * @return A JSONArray of JSONObjects.
198 | * @throws JSONException
199 | */
200 | public static JSONArray toJSONArray(JSONTokener x) throws JSONException {
201 | return toJSONArray(rowToJSONArray(x), x);
202 | }
203 |
204 | /**
205 | * Produce a JSONArray of JSONObjects from a comma delimited text string
206 | * using a supplied JSONArray as the source of element names.
207 | * @param names A JSONArray of strings.
208 | * @param string The comma delimited text.
209 | * @return A JSONArray of JSONObjects.
210 | * @throws JSONException
211 | */
212 | public static JSONArray toJSONArray(JSONArray names, String string)
213 | throws JSONException {
214 | return toJSONArray(names, new JSONTokener(string));
215 | }
216 |
217 | /**
218 | * Produce a JSONArray of JSONObjects from a comma delimited text string
219 | * using a supplied JSONArray as the source of element names.
220 | * @param names A JSONArray of strings.
221 | * @param x A JSONTokener of the source text.
222 | * @return A JSONArray of JSONObjects.
223 | * @throws JSONException
224 | */
225 | public static JSONArray toJSONArray(JSONArray names, JSONTokener x)
226 | throws JSONException {
227 | if (names == null || names.length() == 0) {
228 | return null;
229 | }
230 | JSONArray ja = new JSONArray();
231 | for (;;) {
232 | JSONObject jo = rowToJSONObject(names, x);
233 | if (jo == null) {
234 | break;
235 | }
236 | ja.put(jo);
237 | }
238 | if (ja.length() == 0) {
239 | return null;
240 | }
241 | return ja;
242 | }
243 |
244 |
245 | /**
246 | * Produce a comma delimited text from a JSONArray of JSONObjects. The
247 | * first row will be a list of names obtained by inspecting the first
248 | * JSONObject.
249 | * @param ja A JSONArray of JSONObjects.
250 | * @return A comma delimited text.
251 | * @throws JSONException
252 | */
253 | public static String toString(JSONArray ja) throws JSONException {
254 | JSONObject jo = ja.optJSONObject(0);
255 | if (jo != null) {
256 | JSONArray names = jo.names();
257 | if (names != null) {
258 | return rowToString(names) + toString(names, ja);
259 | }
260 | }
261 | return null;
262 | }
263 |
264 | /**
265 | * Produce a comma delimited text from a JSONArray of JSONObjects using
266 | * a provided list of names. The list of names is not included in the
267 | * output.
268 | * @param names A JSONArray of strings.
269 | * @param ja A JSONArray of JSONObjects.
270 | * @return A comma delimited text.
271 | * @throws JSONException
272 | */
273 | public static String toString(JSONArray names, JSONArray ja)
274 | throws JSONException {
275 | if (names == null || names.length() == 0) {
276 | return null;
277 | }
278 | StringBuffer sb = new StringBuffer();
279 | for (int i = 0; i < ja.length(); i += 1) {
280 | JSONObject jo = ja.optJSONObject(i);
281 | if (jo != null) {
282 | sb.append(rowToString(jo.toJSONArray(names)));
283 | }
284 | }
285 | return sb.toString();
286 | }
287 | }
288 |
--------------------------------------------------------------------------------
/java-version/src/org/json/Cookie.java:
--------------------------------------------------------------------------------
1 | package org.json;
2 |
3 | /*
4 | Copyright (c) 2002 JSON.org
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | The Software shall be used for Good, not Evil.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | SOFTWARE.
25 | */
26 |
27 | /**
28 | * Convert a web browser cookie specification to a JSONObject and back.
29 | * JSON and Cookies are both notations for name/value pairs.
30 | * @author JSON.org
31 | * @version 2015-12-09
32 | */
33 | public class Cookie {
34 |
35 | /**
36 | * Produce a copy of a string in which the characters '+', '%', '=', ';'
37 | * and control characters are replaced with "%hh". This is a gentle form
38 | * of URL encoding, attempting to cause as little distortion to the
39 | * string as possible. The characters '=' and ';' are meta characters in
40 | * cookies. By convention, they are escaped using the URL-encoding. This is
41 | * only a convention, not a standard. Often, cookies are expected to have
42 | * encoded values. We encode '=' and ';' because we must. We encode '%' and
43 | * '+' because they are meta characters in URL encoding.
44 | * @param string The source string.
45 | * @return The escaped result.
46 | */
47 | public static String escape(String string) {
48 | char c;
49 | String s = string.trim();
50 | int length = s.length();
51 | StringBuilder sb = new StringBuilder(length);
52 | for (int i = 0; i < length; i += 1) {
53 | c = s.charAt(i);
54 | if (c < ' ' || c == '+' || c == '%' || c == '=' || c == ';') {
55 | sb.append('%');
56 | sb.append(Character.forDigit((char)((c >>> 4) & 0x0f), 16));
57 | sb.append(Character.forDigit((char)(c & 0x0f), 16));
58 | } else {
59 | sb.append(c);
60 | }
61 | }
62 | return sb.toString();
63 | }
64 |
65 |
66 | /**
67 | * Convert a cookie specification string into a JSONObject. The string
68 | * will contain a name value pair separated by '='. The name and the value
69 | * will be unescaped, possibly converting '+' and '%' sequences. The
70 | * cookie properties may follow, separated by ';', also represented as
71 | * name=value (except the secure property, which does not have a value).
72 | * The name will be stored under the key "name", and the value will be
73 | * stored under the key "value". This method does not do checking or
74 | * validation of the parameters. It only converts the cookie string into
75 | * a JSONObject.
76 | * @param string The cookie specification string.
77 | * @return A JSONObject containing "name", "value", and possibly other
78 | * members.
79 | * @throws JSONException
80 | */
81 | public static JSONObject toJSONObject(String string) throws JSONException {
82 | String name;
83 | JSONObject jo = new JSONObject();
84 | Object value;
85 | JSONTokener x = new JSONTokener(string);
86 | jo.put("name", x.nextTo('='));
87 | x.next('=');
88 | jo.put("value", x.nextTo(';'));
89 | x.next();
90 | while (x.more()) {
91 | name = unescape(x.nextTo("=;"));
92 | if (x.next() != '=') {
93 | if (name.equals("secure")) {
94 | value = Boolean.TRUE;
95 | } else {
96 | throw x.syntaxError("Missing '=' in cookie parameter.");
97 | }
98 | } else {
99 | value = unescape(x.nextTo(';'));
100 | x.next();
101 | }
102 | jo.put(name, value);
103 | }
104 | return jo;
105 | }
106 |
107 |
108 | /**
109 | * Convert a JSONObject into a cookie specification string. The JSONObject
110 | * must contain "name" and "value" members.
111 | * If the JSONObject contains "expires", "domain", "path", or "secure"
112 | * members, they will be appended to the cookie specification string.
113 | * All other members are ignored.
114 | * @param jo A JSONObject
115 | * @return A cookie specification string
116 | * @throws JSONException
117 | */
118 | public static String toString(JSONObject jo) throws JSONException {
119 | StringBuilder sb = new StringBuilder();
120 |
121 | sb.append(escape(jo.getString("name")));
122 | sb.append("=");
123 | sb.append(escape(jo.getString("value")));
124 | if (jo.has("expires")) {
125 | sb.append(";expires=");
126 | sb.append(jo.getString("expires"));
127 | }
128 | if (jo.has("domain")) {
129 | sb.append(";domain=");
130 | sb.append(escape(jo.getString("domain")));
131 | }
132 | if (jo.has("path")) {
133 | sb.append(";path=");
134 | sb.append(escape(jo.getString("path")));
135 | }
136 | if (jo.optBoolean("secure")) {
137 | sb.append(";secure");
138 | }
139 | return sb.toString();
140 | }
141 |
142 | /**
143 | * Convert %
hh sequences to single characters, and
144 | * convert plus to space.
145 | * @param string A string that may contain
146 | * +
(plus) and
147 | * %
hh sequences.
148 | * @return The unescaped string.
149 | */
150 | public static String unescape(String string) {
151 | int length = string.length();
152 | StringBuilder sb = new StringBuilder(length);
153 | for (int i = 0; i < length; ++i) {
154 | char c = string.charAt(i);
155 | if (c == '+') {
156 | c = ' ';
157 | } else if (c == '%' && i + 2 < length) {
158 | int d = JSONTokener.dehexchar(string.charAt(i + 1));
159 | int e = JSONTokener.dehexchar(string.charAt(i + 2));
160 | if (d >= 0 && e >= 0) {
161 | c = (char)(d * 16 + e);
162 | i += 2;
163 | }
164 | }
165 | sb.append(c);
166 | }
167 | return sb.toString();
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/java-version/src/org/json/CookieList.java:
--------------------------------------------------------------------------------
1 | package org.json;
2 |
3 | /*
4 | Copyright (c) 2002 JSON.org
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | The Software shall be used for Good, not Evil.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | SOFTWARE.
25 | */
26 |
27 | /**
28 | * Convert a web browser cookie list string to a JSONObject and back.
29 | * @author JSON.org
30 | * @version 2015-12-09
31 | */
32 | public class CookieList {
33 |
34 | /**
35 | * Convert a cookie list into a JSONObject. A cookie list is a sequence
36 | * of name/value pairs. The names are separated from the values by '='.
37 | * The pairs are separated by ';'. The names and the values
38 | * will be unescaped, possibly converting '+' and '%' sequences.
39 | *
40 | * To add a cookie to a cookie list,
41 | * cookielistJSONObject.put(cookieJSONObject.getString("name"),
42 | * cookieJSONObject.getString("value"));
43 | * @param string A cookie list string
44 | * @return A JSONObject
45 | * @throws JSONException
46 | */
47 | public static JSONObject toJSONObject(String string) throws JSONException {
48 | JSONObject jo = new JSONObject();
49 | JSONTokener x = new JSONTokener(string);
50 | while (x.more()) {
51 | String name = Cookie.unescape(x.nextTo('='));
52 | x.next('=');
53 | jo.put(name, Cookie.unescape(x.nextTo(';')));
54 | x.next();
55 | }
56 | return jo;
57 | }
58 |
59 | /**
60 | * Convert a JSONObject into a cookie list. A cookie list is a sequence
61 | * of name/value pairs. The names are separated from the values by '='.
62 | * The pairs are separated by ';'. The characters '%', '+', '=', and ';'
63 | * in the names and values are replaced by "%hh".
64 | * @param jo A JSONObject
65 | * @return A cookie list string
66 | * @throws JSONException
67 | */
68 | public static String toString(JSONObject jo) throws JSONException {
69 | boolean b = false;
70 | final StringBuilder sb = new StringBuilder();
71 | // Don't use the new entrySet API to maintain Android support
72 | for (final String key : jo.keySet()) {
73 | final Object value = jo.opt(key);
74 | if (!JSONObject.NULL.equals(value)) {
75 | if (b) {
76 | sb.append(';');
77 | }
78 | sb.append(Cookie.escape(key));
79 | sb.append("=");
80 | sb.append(Cookie.escape(value.toString()));
81 | b = true;
82 | }
83 | }
84 | return sb.toString();
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/java-version/src/org/json/HTTP.java:
--------------------------------------------------------------------------------
1 | package org.json;
2 |
3 | /*
4 | Copyright (c) 2002 JSON.org
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | The Software shall be used for Good, not Evil.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | SOFTWARE.
25 | */
26 |
27 | import java.util.Locale;
28 |
29 | /**
30 | * Convert an HTTP header to a JSONObject and back.
31 | * @author JSON.org
32 | * @version 2015-12-09
33 | */
34 | public class HTTP {
35 |
36 | /** Carriage return/line feed. */
37 | public static final String CRLF = "\r\n";
38 |
39 | /**
40 | * Convert an HTTP header string into a JSONObject. It can be a request
41 | * header or a response header. A request header will contain
42 | *
{ 43 | * Method: "POST" (for example), 44 | * "Request-URI": "/" (for example), 45 | * "HTTP-Version": "HTTP/1.1" (for example) 46 | * }47 | * A response header will contain 48 | *
{ 49 | * "HTTP-Version": "HTTP/1.1" (for example), 50 | * "Status-Code": "200" (for example), 51 | * "Reason-Phrase": "OK" (for example) 52 | * }53 | * In addition, the other parameters in the header will be captured, using 54 | * the HTTP field names as JSON names, so that
55 | * Date: Sun, 26 May 2002 18:06:04 GMT 56 | * Cookie: Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s 57 | * Cache-Control: no-cache58 | * become 59 | *
{... 60 | * Date: "Sun, 26 May 2002 18:06:04 GMT", 61 | * Cookie: "Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s", 62 | * "Cache-Control": "no-cache", 63 | * ...}64 | * It does no further checking or conversion. It does not parse dates. 65 | * It does not do '%' transforms on URLs. 66 | * @param string An HTTP header string. 67 | * @return A JSONObject containing the elements and attributes 68 | * of the XML string. 69 | * @throws JSONException 70 | */ 71 | public static JSONObject toJSONObject(String string) throws JSONException { 72 | JSONObject jo = new JSONObject(); 73 | HTTPTokener x = new HTTPTokener(string); 74 | String token; 75 | 76 | token = x.nextToken(); 77 | if (token.toUpperCase(Locale.ROOT).startsWith("HTTP")) { 78 | 79 | // Response 80 | 81 | jo.put("HTTP-Version", token); 82 | jo.put("Status-Code", x.nextToken()); 83 | jo.put("Reason-Phrase", x.nextTo('\0')); 84 | x.next(); 85 | 86 | } else { 87 | 88 | // Request 89 | 90 | jo.put("Method", token); 91 | jo.put("Request-URI", x.nextToken()); 92 | jo.put("HTTP-Version", x.nextToken()); 93 | } 94 | 95 | // Fields 96 | 97 | while (x.more()) { 98 | String name = x.nextTo(':'); 99 | x.next(':'); 100 | jo.put(name, x.nextTo('\0')); 101 | x.next(); 102 | } 103 | return jo; 104 | } 105 | 106 | 107 | /** 108 | * Convert a JSONObject into an HTTP header. A request header must contain 109 | *
{ 110 | * Method: "POST" (for example), 111 | * "Request-URI": "/" (for example), 112 | * "HTTP-Version": "HTTP/1.1" (for example) 113 | * }114 | * A response header must contain 115 | *
{ 116 | * "HTTP-Version": "HTTP/1.1" (for example), 117 | * "Status-Code": "200" (for example), 118 | * "Reason-Phrase": "OK" (for example) 119 | * }120 | * Any other members of the JSONObject will be output as HTTP fields. 121 | * The result will end with two CRLF pairs. 122 | * @param jo A JSONObject 123 | * @return An HTTP header string. 124 | * @throws JSONException if the object does not contain enough 125 | * information. 126 | */ 127 | public static String toString(JSONObject jo) throws JSONException { 128 | StringBuilder sb = new StringBuilder(); 129 | if (jo.has("Status-Code") && jo.has("Reason-Phrase")) { 130 | sb.append(jo.getString("HTTP-Version")); 131 | sb.append(' '); 132 | sb.append(jo.getString("Status-Code")); 133 | sb.append(' '); 134 | sb.append(jo.getString("Reason-Phrase")); 135 | } else if (jo.has("Method") && jo.has("Request-URI")) { 136 | sb.append(jo.getString("Method")); 137 | sb.append(' '); 138 | sb.append('"'); 139 | sb.append(jo.getString("Request-URI")); 140 | sb.append('"'); 141 | sb.append(' '); 142 | sb.append(jo.getString("HTTP-Version")); 143 | } else { 144 | throw new JSONException("Not enough material for an HTTP header."); 145 | } 146 | sb.append(CRLF); 147 | // Don't use the new entrySet API to maintain Android support 148 | for (final String key : jo.keySet()) { 149 | String value = jo.optString(key); 150 | if (!"HTTP-Version".equals(key) && !"Status-Code".equals(key) && 151 | !"Reason-Phrase".equals(key) && !"Method".equals(key) && 152 | !"Request-URI".equals(key) && !JSONObject.NULL.equals(value)) { 153 | sb.append(key); 154 | sb.append(": "); 155 | sb.append(jo.optString(key)); 156 | sb.append(CRLF); 157 | } 158 | } 159 | sb.append(CRLF); 160 | return sb.toString(); 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /java-version/src/org/json/HTTPTokener.java: -------------------------------------------------------------------------------- 1 | package org.json; 2 | 3 | /* 4 | Copyright (c) 2002 JSON.org 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | The Software shall be used for Good, not Evil. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | /** 28 | * The HTTPTokener extends the JSONTokener to provide additional methods 29 | * for the parsing of HTTP headers. 30 | * @author JSON.org 31 | * @version 2015-12-09 32 | */ 33 | public class HTTPTokener extends JSONTokener { 34 | 35 | /** 36 | * Construct an HTTPTokener from a string. 37 | * @param string A source string. 38 | */ 39 | public HTTPTokener(String string) { 40 | super(string); 41 | } 42 | 43 | 44 | /** 45 | * Get the next token or string. This is used in parsing HTTP headers. 46 | * @throws JSONException 47 | * @return A String. 48 | */ 49 | public String nextToken() throws JSONException { 50 | char c; 51 | char q; 52 | StringBuilder sb = new StringBuilder(); 53 | do { 54 | c = next(); 55 | } while (Character.isWhitespace(c)); 56 | if (c == '"' || c == '\'') { 57 | q = c; 58 | for (;;) { 59 | c = next(); 60 | if (c < ' ') { 61 | throw syntaxError("Unterminated string."); 62 | } 63 | if (c == q) { 64 | return sb.toString(); 65 | } 66 | sb.append(c); 67 | } 68 | } 69 | for (;;) { 70 | if (c == 0 || Character.isWhitespace(c)) { 71 | return sb.toString(); 72 | } 73 | sb.append(c); 74 | c = next(); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /java-version/src/org/json/JSONException.java: -------------------------------------------------------------------------------- 1 | package org.json; 2 | 3 | /** 4 | * The JSONException is thrown by the JSON.org classes when things are amiss. 5 | * 6 | * @author JSON.org 7 | * @version 2015-12-09 8 | */ 9 | public class JSONException extends RuntimeException { 10 | /** Serialization ID */ 11 | private static final long serialVersionUID = 0; 12 | 13 | /** 14 | * Constructs a JSONException with an explanatory message. 15 | * 16 | * @param message 17 | * Detail about the reason for the exception. 18 | */ 19 | public JSONException(final String message) { 20 | super(message); 21 | } 22 | 23 | /** 24 | * Constructs a JSONException with an explanatory message and cause. 25 | * 26 | * @param message 27 | * Detail about the reason for the exception. 28 | * @param cause 29 | * The cause. 30 | */ 31 | public JSONException(final String message, final Throwable cause) { 32 | super(message, cause); 33 | } 34 | 35 | /** 36 | * Constructs a new JSONException with the specified cause. 37 | * 38 | * @param cause 39 | * The cause. 40 | */ 41 | public JSONException(final Throwable cause) { 42 | super(cause.getMessage(), cause); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /java-version/src/org/json/JSONML.java: -------------------------------------------------------------------------------- 1 | package org.json; 2 | 3 | /* 4 | Copyright (c) 2008 JSON.org 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | The Software shall be used for Good, not Evil. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | /** 28 | * This provides static methods to convert an XML text into a JSONArray or 29 | * JSONObject, and to covert a JSONArray or JSONObject into an XML text using 30 | * the JsonML transform. 31 | * 32 | * @author JSON.org 33 | * @version 2016-01-30 34 | */ 35 | public class JSONML { 36 | /** 37 | * Parse XML values and store them in a JSONArray. 38 | * @param x The XMLTokener containing the source string. 39 | * @param arrayForm true if array form, false if object form. 40 | * @param ja The JSONArray that is containing the current tag or null 41 | * if we are at the outermost level. 42 | * @param keepStrings Don't type-convert text nodes and attribute values 43 | * @return A JSONArray if the value is the outermost tag, otherwise null. 44 | * @throws JSONException 45 | */ 46 | private static Object parse( 47 | XMLTokener x, 48 | boolean arrayForm, 49 | JSONArray ja, 50 | boolean keepStrings 51 | ) throws JSONException { 52 | String attribute; 53 | char c; 54 | String closeTag = null; 55 | int i; 56 | JSONArray newja = null; 57 | JSONObject newjo = null; 58 | Object token; 59 | String tagName = null; 60 | 61 | // Test for and skip past these forms: 62 | // 63 | // 64 | // 65 | // ... ?> 66 | 67 | while (true) { 68 | if (!x.more()) { 69 | throw x.syntaxError("Bad XML"); 70 | } 71 | token = x.nextContent(); 72 | if (token == XML.LT) { 73 | token = x.nextToken(); 74 | if (token instanceof Character) { 75 | if (token == XML.SLASH) { 76 | 77 | // Close tag 78 | 79 | token = x.nextToken(); 80 | if (!(token instanceof String)) { 81 | throw new JSONException( 82 | "Expected a closing name instead of '" + 83 | token + "'."); 84 | } 85 | if (x.nextToken() != XML.GT) { 86 | throw x.syntaxError("Misshaped close tag"); 87 | } 88 | return token; 89 | } else if (token == XML.BANG) { 90 | 91 | // "); 97 | } else { 98 | x.back(); 99 | } 100 | } else if (c == '[') { 101 | token = x.nextToken(); 102 | if (token.equals("CDATA") && x.next() == '[') { 103 | if (ja != null) { 104 | ja.put(x.nextCDATA()); 105 | } 106 | } else { 107 | throw x.syntaxError("Expected 'CDATA['"); 108 | } 109 | } else { 110 | i = 1; 111 | do { 112 | token = x.nextMeta(); 113 | if (token == null) { 114 | throw x.syntaxError("Missing '>' after ' 0); 121 | } 122 | } else if (token == XML.QUEST) { 123 | 124 | // 125 | 126 | x.skipPast("?>"); 127 | } else { 128 | throw x.syntaxError("Misshaped tag"); 129 | } 130 | 131 | // Open tag < 132 | 133 | } else { 134 | if (!(token instanceof String)) { 135 | throw x.syntaxError("Bad tagName '" + token + "'."); 136 | } 137 | tagName = (String)token; 138 | newja = new JSONArray(); 139 | newjo = new JSONObject(); 140 | if (arrayForm) { 141 | newja.put(tagName); 142 | if (ja != null) { 143 | ja.put(newja); 144 | } 145 | } else { 146 | newjo.put("tagName", tagName); 147 | if (ja != null) { 148 | ja.put(newjo); 149 | } 150 | } 151 | token = null; 152 | for (;;) { 153 | if (token == null) { 154 | token = x.nextToken(); 155 | } 156 | if (token == null) { 157 | throw x.syntaxError("Misshaped tag"); 158 | } 159 | if (!(token instanceof String)) { 160 | break; 161 | } 162 | 163 | // attribute = value 164 | 165 | attribute = (String)token; 166 | if (!arrayForm && ("tagName".equals(attribute) || "childNode".equals(attribute))) { 167 | throw x.syntaxError("Reserved attribute."); 168 | } 169 | token = x.nextToken(); 170 | if (token == XML.EQ) { 171 | token = x.nextToken(); 172 | if (!(token instanceof String)) { 173 | throw x.syntaxError("Missing value"); 174 | } 175 | newjo.accumulate(attribute, keepStrings ? ((String)token) :XML.stringToValue((String)token)); 176 | token = null; 177 | } else { 178 | newjo.accumulate(attribute, ""); 179 | } 180 | } 181 | if (arrayForm && newjo.length() > 0) { 182 | newja.put(newjo); 183 | } 184 | 185 | // Empty tag <.../> 186 | 187 | if (token == XML.SLASH) { 188 | if (x.nextToken() != XML.GT) { 189 | throw x.syntaxError("Misshaped tag"); 190 | } 191 | if (ja == null) { 192 | if (arrayForm) { 193 | return newja; 194 | } 195 | return newjo; 196 | } 197 | 198 | // Content, between <...> and 199 | 200 | } else { 201 | if (token != XML.GT) { 202 | throw x.syntaxError("Misshaped tag"); 203 | } 204 | closeTag = (String)parse(x, arrayForm, newja, keepStrings); 205 | if (closeTag != null) { 206 | if (!closeTag.equals(tagName)) { 207 | throw x.syntaxError("Mismatched '" + tagName + 208 | "' and '" + closeTag + "'"); 209 | } 210 | tagName = null; 211 | if (!arrayForm && newja.length() > 0) { 212 | newjo.put("childNodes", newja); 213 | } 214 | if (ja == null) { 215 | if (arrayForm) { 216 | return newja; 217 | } 218 | return newjo; 219 | } 220 | } 221 | } 222 | } 223 | } else { 224 | if (ja != null) { 225 | ja.put(token instanceof String 226 | ? keepStrings ? XML.unescape((String)token) :XML.stringToValue((String)token) 227 | : token); 228 | } 229 | } 230 | } 231 | } 232 | 233 | 234 | /** 235 | * Convert a well-formed (but not necessarily valid) XML string into a 236 | * JSONArray using the JsonML transform. Each XML tag is represented as 237 | * a JSONArray in which the first element is the tag name. If the tag has 238 | * attributes, then the second element will be JSONObject containing the 239 | * name/value pairs. If the tag contains children, then strings and 240 | * JSONArrays will represent the child tags. 241 | * Comments, prologs, DTDs, and
<[ [ ]]>
are ignored.
242 | * @param string The source string.
243 | * @return A JSONArray containing the structured data from the XML string.
244 | * @throws JSONException Thrown on error converting to a JSONArray
245 | */
246 | public static JSONArray toJSONArray(String string) throws JSONException {
247 | return (JSONArray)parse(new XMLTokener(string), true, null, false);
248 | }
249 |
250 |
251 | /**
252 | * Convert a well-formed (but not necessarily valid) XML string into a
253 | * JSONArray using the JsonML transform. Each XML tag is represented as
254 | * a JSONArray in which the first element is the tag name. If the tag has
255 | * attributes, then the second element will be JSONObject containing the
256 | * name/value pairs. If the tag contains children, then strings and
257 | * JSONArrays will represent the child tags.
258 | * As opposed to toJSONArray this method does not attempt to convert
259 | * any text node or attribute value to any type
260 | * but just leaves it as a string.
261 | * Comments, prologs, DTDs, and <[ [ ]]>
are ignored.
262 | * @param string The source string.
263 | * @param keepStrings If true, then values will not be coerced into boolean
264 | * or numeric values and will instead be left as strings
265 | * @return A JSONArray containing the structured data from the XML string.
266 | * @throws JSONException Thrown on error converting to a JSONArray
267 | */
268 | public static JSONArray toJSONArray(String string, boolean keepStrings) throws JSONException {
269 | return (JSONArray)parse(new XMLTokener(string), true, null, keepStrings);
270 | }
271 |
272 |
273 | /**
274 | * Convert a well-formed (but not necessarily valid) XML string into a
275 | * JSONArray using the JsonML transform. Each XML tag is represented as
276 | * a JSONArray in which the first element is the tag name. If the tag has
277 | * attributes, then the second element will be JSONObject containing the
278 | * name/value pairs. If the tag contains children, then strings and
279 | * JSONArrays will represent the child content and tags.
280 | * As opposed to toJSONArray this method does not attempt to convert
281 | * any text node or attribute value to any type
282 | * but just leaves it as a string.
283 | * Comments, prologs, DTDs, and <[ [ ]]>
are ignored.
284 | * @param x An XMLTokener.
285 | * @param keepStrings If true, then values will not be coerced into boolean
286 | * or numeric values and will instead be left as strings
287 | * @return A JSONArray containing the structured data from the XML string.
288 | * @throws JSONException Thrown on error converting to a JSONArray
289 | */
290 | public static JSONArray toJSONArray(XMLTokener x, boolean keepStrings) throws JSONException {
291 | return (JSONArray)parse(x, true, null, keepStrings);
292 | }
293 |
294 |
295 | /**
296 | * Convert a well-formed (but not necessarily valid) XML string into a
297 | * JSONArray using the JsonML transform. Each XML tag is represented as
298 | * a JSONArray in which the first element is the tag name. If the tag has
299 | * attributes, then the second element will be JSONObject containing the
300 | * name/value pairs. If the tag contains children, then strings and
301 | * JSONArrays will represent the child content and tags.
302 | * Comments, prologs, DTDs, and <[ [ ]]>
are ignored.
303 | * @param x An XMLTokener.
304 | * @return A JSONArray containing the structured data from the XML string.
305 | * @throws JSONException Thrown on error converting to a JSONArray
306 | */
307 | public static JSONArray toJSONArray(XMLTokener x) throws JSONException {
308 | return (JSONArray)parse(x, true, null, false);
309 | }
310 |
311 |
312 | /**
313 | * Convert a well-formed (but not necessarily valid) XML string into a
314 | * JSONObject using the JsonML transform. Each XML tag is represented as
315 | * a JSONObject with a "tagName" property. If the tag has attributes, then
316 | * the attributes will be in the JSONObject as properties. If the tag
317 | * contains children, the object will have a "childNodes" property which
318 | * will be an array of strings and JsonML JSONObjects.
319 |
320 | * Comments, prologs, DTDs, and <[ [ ]]>
are ignored.
321 | * @param string The XML source text.
322 | * @return A JSONObject containing the structured data from the XML string.
323 | * @throws JSONException Thrown on error converting to a JSONObject
324 | */
325 | public static JSONObject toJSONObject(String string) throws JSONException {
326 | return (JSONObject)parse(new XMLTokener(string), false, null, false);
327 | }
328 |
329 |
330 | /**
331 | * Convert a well-formed (but not necessarily valid) XML string into a
332 | * JSONObject using the JsonML transform. Each XML tag is represented as
333 | * a JSONObject with a "tagName" property. If the tag has attributes, then
334 | * the attributes will be in the JSONObject as properties. If the tag
335 | * contains children, the object will have a "childNodes" property which
336 | * will be an array of strings and JsonML JSONObjects.
337 |
338 | * Comments, prologs, DTDs, and <[ [ ]]>
are ignored.
339 | * @param string The XML source text.
340 | * @param keepStrings If true, then values will not be coerced into boolean
341 | * or numeric values and will instead be left as strings
342 | * @return A JSONObject containing the structured data from the XML string.
343 | * @throws JSONException Thrown on error converting to a JSONObject
344 | */
345 | public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException {
346 | return (JSONObject)parse(new XMLTokener(string), false, null, keepStrings);
347 | }
348 |
349 |
350 | /**
351 | * Convert a well-formed (but not necessarily valid) XML string into a
352 | * JSONObject using the JsonML transform. Each XML tag is represented as
353 | * a JSONObject with a "tagName" property. If the tag has attributes, then
354 | * the attributes will be in the JSONObject as properties. If the tag
355 | * contains children, the object will have a "childNodes" property which
356 | * will be an array of strings and JsonML JSONObjects.
357 |
358 | * Comments, prologs, DTDs, and <[ [ ]]>
are ignored.
359 | * @param x An XMLTokener of the XML source text.
360 | * @return A JSONObject containing the structured data from the XML string.
361 | * @throws JSONException Thrown on error converting to a JSONObject
362 | */
363 | public static JSONObject toJSONObject(XMLTokener x) throws JSONException {
364 | return (JSONObject)parse(x, false, null, false);
365 | }
366 |
367 |
368 | /**
369 | * Convert a well-formed (but not necessarily valid) XML string into a
370 | * JSONObject using the JsonML transform. Each XML tag is represented as
371 | * a JSONObject with a "tagName" property. If the tag has attributes, then
372 | * the attributes will be in the JSONObject as properties. If the tag
373 | * contains children, the object will have a "childNodes" property which
374 | * will be an array of strings and JsonML JSONObjects.
375 |
376 | * Comments, prologs, DTDs, and <[ [ ]]>
are ignored.
377 | * @param x An XMLTokener of the XML source text.
378 | * @param keepStrings If true, then values will not be coerced into boolean
379 | * or numeric values and will instead be left as strings
380 | * @return A JSONObject containing the structured data from the XML string.
381 | * @throws JSONException Thrown on error converting to a JSONObject
382 | */
383 | public static JSONObject toJSONObject(XMLTokener x, boolean keepStrings) throws JSONException {
384 | return (JSONObject)parse(x, false, null, keepStrings);
385 | }
386 |
387 |
388 | /**
389 | * Reverse the JSONML transformation, making an XML text from a JSONArray.
390 | * @param ja A JSONArray.
391 | * @return An XML string.
392 | * @throws JSONException Thrown on error converting to a string
393 | */
394 | public static String toString(JSONArray ja) throws JSONException {
395 | int i;
396 | JSONObject jo;
397 | int length;
398 | Object object;
399 | StringBuilder sb = new StringBuilder();
400 | String tagName;
401 |
402 | // Emit
113 | * JSONPointer pointer = JSONPointer.builder()
114 | * .append("obj")
115 | * .append("other~key").append("another/key")
116 | * .append("\"")
117 | * .append(0)
118 | * .build();
119 | *
120 | *
121 | * @return a builder instance which can be used to construct a {@code JSONPointer} instance by chained
122 | * {@link Builder#append(String)} calls.
123 | */
124 | public static Builder builder() {
125 | return new Builder();
126 | }
127 |
128 | // Segments for the JSONPointer string
129 | private final List""
40 | * will have the Bean parser fall back to the default field name processing.
41 | */
42 | public @interface JSONPropertyName {
43 | /**
44 | * @return The name of the property as to be used in the JSON Object.
45 | */
46 | String value();
47 | }
48 |
--------------------------------------------------------------------------------
/java-version/src/org/json/JSONString.java:
--------------------------------------------------------------------------------
1 | package org.json;
2 | /**
3 | * The JSONString
interface allows a toJSONString()
4 | * method so that a class can change the behavior of
5 | * JSONObject.toString()
, JSONArray.toString()
,
6 | * and JSONWriter.value(
Object)
. The
7 | * toJSONString
method will be used instead of the default behavior
8 | * of using the Object's toString()
method and quoting the result.
9 | */
10 | public interface JSONString {
11 | /**
12 | * The toJSONString
method allows a class to produce its own JSON
13 | * serialization.
14 | *
15 | * @return A strictly syntactically correct JSON text.
16 | */
17 | public String toJSONString();
18 | }
19 |
--------------------------------------------------------------------------------
/java-version/src/org/json/JSONStringer.java:
--------------------------------------------------------------------------------
1 | package org.json;
2 |
3 | /*
4 | Copyright (c) 2006 JSON.org
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | The Software shall be used for Good, not Evil.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | SOFTWARE.
25 | */
26 |
27 | import java.io.StringWriter;
28 |
29 | /**
30 | * JSONStringer provides a quick and convenient way of producing JSON text.
31 | * The texts produced strictly conform to JSON syntax rules. No whitespace is
32 | * added, so the results are ready for transmission or storage. Each instance of
33 | * JSONStringer can produce one JSON text.
34 | *
35 | * A JSONStringer instance provides a value
method for appending
36 | * values to the
37 | * text, and a key
38 | * method for adding keys before values in objects. There are array
39 | * and endArray
methods that make and bound array values, and
40 | * object
and endObject
methods which make and bound
41 | * object values. All of these methods return the JSONWriter instance,
42 | * permitting cascade style. For example,
43 | * myString = new JSONStringer() 44 | * .object() 45 | * .key("JSON") 46 | * .value("Hello, World!") 47 | * .endObject() 48 | * .toString();which produces the string
49 | * {"JSON":"Hello, World!"}50 | *
51 | * The first method called must be array
or object
.
52 | * There are no methods for adding commas or colons. JSONStringer adds them for
53 | * you. Objects and arrays can be nested up to 20 levels deep.
54 | *
55 | * This can sometimes be easier than using a JSONObject to build a string.
56 | * @author JSON.org
57 | * @version 2015-12-09
58 | */
59 | public class JSONStringer extends JSONWriter {
60 | /**
61 | * Make a fresh JSONStringer. It can be used to build one JSON text.
62 | */
63 | public JSONStringer() {
64 | super(new StringWriter());
65 | }
66 |
67 | /**
68 | * Return the JSON text. This method is used to obtain the product of the
69 | * JSONStringer instance. It will return null
if there was a
70 | * problem in the construction of the JSON text (such as the calls to
71 | * array
were not properly balanced with calls to
72 | * endArray
).
73 | * @return The JSON text.
74 | */
75 | @Override
76 | public String toString() {
77 | return this.mode == 'd' ? this.writer.toString() : null;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/java-version/src/org/json/JSONTokener.java:
--------------------------------------------------------------------------------
1 | package org.json;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.IOException;
5 | import java.io.InputStream;
6 | import java.io.InputStreamReader;
7 | import java.io.Reader;
8 | import java.io.StringReader;
9 |
10 | /*
11 | Copyright (c) 2002 JSON.org
12 |
13 | Permission is hereby granted, free of charge, to any person obtaining a copy
14 | of this software and associated documentation files (the "Software"), to deal
15 | in the Software without restriction, including without limitation the rights
16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 | copies of the Software, and to permit persons to whom the Software is
18 | furnished to do so, subject to the following conditions:
19 |
20 | The above copyright notice and this permission notice shall be included in all
21 | copies or substantial portions of the Software.
22 |
23 | The Software shall be used for Good, not Evil.
24 |
25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 | SOFTWARE.
32 | */
33 |
34 | /**
35 | * A JSONTokener takes a source string and extracts characters and tokens from
36 | * it. It is used by the JSONObject and JSONArray constructors to parse
37 | * JSON source strings.
38 | * @author JSON.org
39 | * @version 2014-05-03
40 | */
41 | public class JSONTokener {
42 | /** current read character position on the current line. */
43 | private long character;
44 | /** flag to indicate if the end of the input has been found. */
45 | private boolean eof;
46 | /** current read index of the input. */
47 | private long index;
48 | /** current line of the input. */
49 | private long line;
50 | /** previous character read from the input. */
51 | private char previous;
52 | /** Reader for the input. */
53 | private final Reader reader;
54 | /** flag to indicate that a previous character was requested. */
55 | private boolean usePrevious;
56 | /** the number of characters read in the previous line. */
57 | private long characterPreviousLine;
58 |
59 |
60 | /**
61 | * Construct a JSONTokener from a Reader. The caller must close the Reader.
62 | *
63 | * @param reader A reader.
64 | */
65 | public JSONTokener(Reader reader) {
66 | this.reader = reader.markSupported()
67 | ? reader
68 | : new BufferedReader(reader);
69 | this.eof = false;
70 | this.usePrevious = false;
71 | this.previous = 0;
72 | this.index = 0;
73 | this.character = 1;
74 | this.characterPreviousLine = 0;
75 | this.line = 1;
76 | }
77 |
78 |
79 | /**
80 | * Construct a JSONTokener from an InputStream. The caller must close the input stream.
81 | * @param inputStream The source.
82 | */
83 | public JSONTokener(InputStream inputStream) {
84 | this(new InputStreamReader(inputStream));
85 | }
86 |
87 |
88 | /**
89 | * Construct a JSONTokener from a string.
90 | *
91 | * @param s A source string.
92 | */
93 | public JSONTokener(String s) {
94 | this(new StringReader(s));
95 | }
96 |
97 |
98 | /**
99 | * Back up one character. This provides a sort of lookahead capability,
100 | * so that you can test for a digit or letter before attempting to parse
101 | * the next number or identifier.
102 | * @throws JSONException Thrown if trying to step back more than 1 step
103 | * or if already at the start of the string
104 | */
105 | public void back() throws JSONException {
106 | if (this.usePrevious || this.index <= 0) {
107 | throw new JSONException("Stepping back two steps is not supported");
108 | }
109 | this.decrementIndexes();
110 | this.usePrevious = true;
111 | this.eof = false;
112 | }
113 |
114 | /**
115 | * Decrements the indexes for the {@link #back()} method based on the previous character read.
116 | */
117 | private void decrementIndexes() {
118 | this.index--;
119 | if(this.previous=='\r' || this.previous == '\n') {
120 | this.line--;
121 | this.character=this.characterPreviousLine ;
122 | } else if(this.character > 0){
123 | this.character--;
124 | }
125 | }
126 |
127 | /**
128 | * Get the hex value of a character (base16).
129 | * @param c A character between '0' and '9' or between 'A' and 'F' or
130 | * between 'a' and 'f'.
131 | * @return An int between 0 and 15, or -1 if c was not a hex digit.
132 | */
133 | public static int dehexchar(char c) {
134 | if (c >= '0' && c <= '9') {
135 | return c - '0';
136 | }
137 | if (c >= 'A' && c <= 'F') {
138 | return c - ('A' - 10);
139 | }
140 | if (c >= 'a' && c <= 'f') {
141 | return c - ('a' - 10);
142 | }
143 | return -1;
144 | }
145 |
146 | /**
147 | * Checks if the end of the input has been reached.
148 | *
149 | * @return true if at the end of the file and we didn't step back
150 | */
151 | public boolean end() {
152 | return this.eof && !this.usePrevious;
153 | }
154 |
155 |
156 | /**
157 | * Determine if the source string still contains characters that next()
158 | * can consume.
159 | * @return true if not yet at the end of the source.
160 | * @throws JSONException thrown if there is an error stepping forward
161 | * or backward while checking for more data.
162 | */
163 | public boolean more() throws JSONException {
164 | if(this.usePrevious) {
165 | return true;
166 | }
167 | try {
168 | this.reader.mark(1);
169 | } catch (IOException e) {
170 | throw new JSONException("Unable to preserve stream position", e);
171 | }
172 | try {
173 | // -1 is EOF, but next() can not consume the null character '\0'
174 | if(this.reader.read() <= 0) {
175 | this.eof = true;
176 | return false;
177 | }
178 | this.reader.reset();
179 | } catch (IOException e) {
180 | throw new JSONException("Unable to read the next character from the stream", e);
181 | }
182 | return true;
183 | }
184 |
185 |
186 | /**
187 | * Get the next character in the source string.
188 | *
189 | * @return The next character, or 0 if past the end of the source string.
190 | * @throws JSONException Thrown if there is an error reading the source string.
191 | */
192 | public char next() throws JSONException {
193 | int c;
194 | if (this.usePrevious) {
195 | this.usePrevious = false;
196 | c = this.previous;
197 | } else {
198 | try {
199 | c = this.reader.read();
200 | } catch (IOException exception) {
201 | throw new JSONException(exception);
202 | }
203 | }
204 | if (c <= 0) { // End of stream
205 | this.eof = true;
206 | return 0;
207 | }
208 | this.incrementIndexes(c);
209 | this.previous = (char) c;
210 | return this.previous;
211 | }
212 |
213 | /**
214 | * Increments the internal indexes according to the previous character
215 | * read and the character passed as the current character.
216 | * @param c the current character read.
217 | */
218 | private void incrementIndexes(int c) {
219 | if(c > 0) {
220 | this.index++;
221 | if(c=='\r') {
222 | this.line++;
223 | this.characterPreviousLine = this.character;
224 | this.character=0;
225 | }else if (c=='\n') {
226 | if(this.previous != '\r') {
227 | this.line++;
228 | this.characterPreviousLine = this.character;
229 | }
230 | this.character=0;
231 | } else {
232 | this.character++;
233 | }
234 | }
235 | }
236 |
237 | /**
238 | * Consume the next character, and check that it matches a specified
239 | * character.
240 | * @param c The character to match.
241 | * @return The character.
242 | * @throws JSONException if the character does not match.
243 | */
244 | public char next(char c) throws JSONException {
245 | char n = this.next();
246 | if (n != c) {
247 | if(n > 0) {
248 | throw this.syntaxError("Expected '" + c + "' and instead saw '" +
249 | n + "'");
250 | }
251 | throw this.syntaxError("Expected '" + c + "' and instead saw ''");
252 | }
253 | return n;
254 | }
255 |
256 |
257 | /**
258 | * Get the next n characters.
259 | *
260 | * @param n The number of characters to take.
261 | * @return A string of n characters.
262 | * @throws JSONException
263 | * Substring bounds error if there are not
264 | * n characters remaining in the source string.
265 | */
266 | public String next(int n) throws JSONException {
267 | if (n == 0) {
268 | return "";
269 | }
270 |
271 | char[] chars = new char[n];
272 | int pos = 0;
273 |
274 | while (pos < n) {
275 | chars[pos] = this.next();
276 | if (this.end()) {
277 | throw this.syntaxError("Substring bounds error");
278 | }
279 | pos += 1;
280 | }
281 | return new String(chars);
282 | }
283 |
284 |
285 | /**
286 | * Get the next char in the string, skipping whitespace.
287 | * @throws JSONException Thrown if there is an error reading the source string.
288 | * @return A character, or 0 if there are no more characters.
289 | */
290 | public char nextClean() throws JSONException {
291 | for (;;) {
292 | char c = this.next();
293 | if (c == 0 || c > ' ') {
294 | return c;
295 | }
296 | }
297 | }
298 |
299 |
300 | /**
301 | * Return the characters up to the next close quote character.
302 | * Backslash processing is done. The formal JSON format does not
303 | * allow strings in single quotes, but an implementation is allowed to
304 | * accept them.
305 | * @param quote The quoting character, either
306 | * "
(double quote) or
307 | * '
(single quote).
308 | * @return A String.
309 | * @throws JSONException Unterminated string.
310 | */
311 | public String nextString(char quote) throws JSONException {
312 | char c;
313 | StringBuilder sb = new StringBuilder();
314 | for (;;) {
315 | c = this.next();
316 | switch (c) {
317 | case 0:
318 | case '\n':
319 | case '\r':
320 | throw this.syntaxError("Unterminated string");
321 | case '\\':
322 | c = this.next();
323 | switch (c) {
324 | case 'b':
325 | sb.append('\b');
326 | break;
327 | case 't':
328 | sb.append('\t');
329 | break;
330 | case 'n':
331 | sb.append('\n');
332 | break;
333 | case 'f':
334 | sb.append('\f');
335 | break;
336 | case 'r':
337 | sb.append('\r');
338 | break;
339 | case 'u':
340 | try {
341 | sb.append((char)Integer.parseInt(this.next(4), 16));
342 | } catch (NumberFormatException e) {
343 | throw this.syntaxError("Illegal escape.", e);
344 | }
345 | break;
346 | case '"':
347 | case '\'':
348 | case '\\':
349 | case '/':
350 | sb.append(c);
351 | break;
352 | default:
353 | throw this.syntaxError("Illegal escape.");
354 | }
355 | break;
356 | default:
357 | if (c == quote) {
358 | return sb.toString();
359 | }
360 | sb.append(c);
361 | }
362 | }
363 | }
364 |
365 |
366 | /**
367 | * Get the text up but not including the specified character or the
368 | * end of line, whichever comes first.
369 | * @param delimiter A delimiter character.
370 | * @return A string.
371 | * @throws JSONException Thrown if there is an error while searching
372 | * for the delimiter
373 | */
374 | public String nextTo(char delimiter) throws JSONException {
375 | StringBuilder sb = new StringBuilder();
376 | for (;;) {
377 | char c = this.next();
378 | if (c == delimiter || c == 0 || c == '\n' || c == '\r') {
379 | if (c != 0) {
380 | this.back();
381 | }
382 | return sb.toString().trim();
383 | }
384 | sb.append(c);
385 | }
386 | }
387 |
388 |
389 | /**
390 | * Get the text up but not including one of the specified delimiter
391 | * characters or the end of line, whichever comes first.
392 | * @param delimiters A set of delimiter characters.
393 | * @return A string, trimmed.
394 | * @throws JSONException Thrown if there is an error while searching
395 | * for the delimiter
396 | */
397 | public String nextTo(String delimiters) throws JSONException {
398 | char c;
399 | StringBuilder sb = new StringBuilder();
400 | for (;;) {
401 | c = this.next();
402 | if (delimiters.indexOf(c) >= 0 || c == 0 ||
403 | c == '\n' || c == '\r') {
404 | if (c != 0) {
405 | this.back();
406 | }
407 | return sb.toString().trim();
408 | }
409 | sb.append(c);
410 | }
411 | }
412 |
413 |
414 | /**
415 | * Get the next value. The value can be a Boolean, Double, Integer,
416 | * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object.
417 | * @throws JSONException If syntax error.
418 | *
419 | * @return An object.
420 | */
421 | public Object nextValue() throws JSONException {
422 | char c = this.nextClean();
423 | String string;
424 |
425 | switch (c) {
426 | case '"':
427 | case '\'':
428 | return this.nextString(c);
429 | case '{':
430 | this.back();
431 | return new JSONObject(this);
432 | case '[':
433 | this.back();
434 | return new JSONArray(this);
435 | }
436 |
437 | /*
438 | * Handle unquoted text. This could be the values true, false, or
439 | * null, or it can be a number. An implementation (such as this one)
440 | * is allowed to also accept non-standard forms.
441 | *
442 | * Accumulate characters until we reach the end of the text or a
443 | * formatting character.
444 | */
445 |
446 | StringBuilder sb = new StringBuilder();
447 | while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) {
448 | sb.append(c);
449 | c = this.next();
450 | }
451 | this.back();
452 |
453 | string = sb.toString().trim();
454 | if ("".equals(string)) {
455 | throw this.syntaxError("Missing value");
456 | }
457 | return JSONObject.stringToValue(string);
458 | }
459 |
460 |
461 | /**
462 | * Skip characters until the next character is the requested character.
463 | * If the requested character is not found, no characters are skipped.
464 | * @param to A character to skip to.
465 | * @return The requested character, or zero if the requested character
466 | * is not found.
467 | * @throws JSONException Thrown if there is an error while searching
468 | * for the to character
469 | */
470 | public char skipTo(char to) throws JSONException {
471 | char c;
472 | try {
473 | long startIndex = this.index;
474 | long startCharacter = this.character;
475 | long startLine = this.line;
476 | this.reader.mark(1000000);
477 | do {
478 | c = this.next();
479 | if (c == 0) {
480 | // in some readers, reset() may throw an exception if
481 | // the remaining portion of the input is greater than
482 | // the mark size (1,000,000 above).
483 | this.reader.reset();
484 | this.index = startIndex;
485 | this.character = startCharacter;
486 | this.line = startLine;
487 | return 0;
488 | }
489 | } while (c != to);
490 | this.reader.mark(1);
491 | } catch (IOException exception) {
492 | throw new JSONException(exception);
493 | }
494 | this.back();
495 | return c;
496 | }
497 |
498 | /**
499 | * Make a JSONException to signal a syntax error.
500 | *
501 | * @param message The error message.
502 | * @return A JSONException object, suitable for throwing
503 | */
504 | public JSONException syntaxError(String message) {
505 | return new JSONException(message + this.toString());
506 | }
507 |
508 | /**
509 | * Make a JSONException to signal a syntax error.
510 | *
511 | * @param message The error message.
512 | * @param causedBy The throwable that caused the error.
513 | * @return A JSONException object, suitable for throwing
514 | */
515 | public JSONException syntaxError(String message, Throwable causedBy) {
516 | return new JSONException(message + this.toString(), causedBy);
517 | }
518 |
519 | /**
520 | * Make a printable string of this JSONTokener.
521 | *
522 | * @return " at {index} [character {character} line {line}]"
523 | */
524 | @Override
525 | public String toString() {
526 | return " at " + this.index + " [character " + this.character + " line " +
527 | this.line + "]";
528 | }
529 | }
530 |
--------------------------------------------------------------------------------
/java-version/src/org/json/JSONWriter.java:
--------------------------------------------------------------------------------
1 | package org.json;
2 |
3 | import java.io.IOException;
4 | import java.math.BigDecimal;
5 | import java.util.Collection;
6 | import java.util.Map;
7 |
8 | /*
9 | Copyright (c) 2006 JSON.org
10 |
11 | Permission is hereby granted, free of charge, to any person obtaining a copy
12 | of this software and associated documentation files (the "Software"), to deal
13 | in the Software without restriction, including without limitation the rights
14 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | copies of the Software, and to permit persons to whom the Software is
16 | furnished to do so, subject to the following conditions:
17 |
18 | The above copyright notice and this permission notice shall be included in all
19 | copies or substantial portions of the Software.
20 |
21 | The Software shall be used for Good, not Evil.
22 |
23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 | SOFTWARE.
30 | */
31 |
32 | /**
33 | * JSONWriter provides a quick and convenient way of producing JSON text.
34 | * The texts produced strictly conform to JSON syntax rules. No whitespace is
35 | * added, so the results are ready for transmission or storage. Each instance of
36 | * JSONWriter can produce one JSON text.
37 | *
38 | * A JSONWriter instance provides a value
method for appending
39 | * values to the
40 | * text, and a key
41 | * method for adding keys before values in objects. There are array
42 | * and endArray
methods that make and bound array values, and
43 | * object
and endObject
methods which make and bound
44 | * object values. All of these methods return the JSONWriter instance,
45 | * permitting a cascade style. For example,
46 | * new JSONWriter(myWriter) 47 | * .object() 48 | * .key("JSON") 49 | * .value("Hello, World!") 50 | * .endObject();which writes
51 | * {"JSON":"Hello, World!"}52 | *
53 | * The first method called must be array
or object
.
54 | * There are no methods for adding commas or colons. JSONWriter adds them for
55 | * you. Objects and arrays can be nested up to 200 levels deep.
56 | *
57 | * This can sometimes be easier than using a JSONObject to build a string.
58 | * @author JSON.org
59 | * @version 2016-08-08
60 | */
61 | public class JSONWriter {
62 | private static final int maxdepth = 200;
63 |
64 | /**
65 | * The comma flag determines if a comma should be output before the next
66 | * value.
67 | */
68 | private boolean comma;
69 |
70 | /**
71 | * The current mode. Values:
72 | * 'a' (array),
73 | * 'd' (done),
74 | * 'i' (initial),
75 | * 'k' (key),
76 | * 'o' (object).
77 | */
78 | protected char mode;
79 |
80 | /**
81 | * The object/array stack.
82 | */
83 | private final JSONObject stack[];
84 |
85 | /**
86 | * The stack top index. A value of 0 indicates that the stack is empty.
87 | */
88 | private int top;
89 |
90 | /**
91 | * The writer that will receive the output.
92 | */
93 | protected Appendable writer;
94 |
95 | /**
96 | * Make a fresh JSONWriter. It can be used to build one JSON text.
97 | */
98 | public JSONWriter(Appendable w) {
99 | this.comma = false;
100 | this.mode = 'i';
101 | this.stack = new JSONObject[maxdepth];
102 | this.top = 0;
103 | this.writer = w;
104 | }
105 |
106 | /**
107 | * Append a value.
108 | * @param string A string value.
109 | * @return this
110 | * @throws JSONException If the value is out of sequence.
111 | */
112 | private JSONWriter append(String string) throws JSONException {
113 | if (string == null) {
114 | throw new JSONException("Null pointer");
115 | }
116 | if (this.mode == 'o' || this.mode == 'a') {
117 | try {
118 | if (this.comma && this.mode == 'a') {
119 | this.writer.append(',');
120 | }
121 | this.writer.append(string);
122 | } catch (IOException e) {
123 | // Android as of API 25 does not support this exception constructor
124 | // however we won't worry about it. If an exception is happening here
125 | // it will just throw a "Method not found" exception instead.
126 | throw new JSONException(e);
127 | }
128 | if (this.mode == 'o') {
129 | this.mode = 'k';
130 | }
131 | this.comma = true;
132 | return this;
133 | }
134 | throw new JSONException("Value out of sequence.");
135 | }
136 |
137 | /**
138 | * Begin appending a new array. All values until the balancing
139 | * endArray
will be appended to this array. The
140 | * endArray
method must be called to mark the array's end.
141 | * @return this
142 | * @throws JSONException If the nesting is too deep, or if the object is
143 | * started in the wrong place (for example as a key or after the end of the
144 | * outermost array or object).
145 | */
146 | public JSONWriter array() throws JSONException {
147 | if (this.mode == 'i' || this.mode == 'o' || this.mode == 'a') {
148 | this.push(null);
149 | this.append("[");
150 | this.comma = false;
151 | return this;
152 | }
153 | throw new JSONException("Misplaced array.");
154 | }
155 |
156 | /**
157 | * End something.
158 | * @param m Mode
159 | * @param c Closing character
160 | * @return this
161 | * @throws JSONException If unbalanced.
162 | */
163 | private JSONWriter end(char m, char c) throws JSONException {
164 | if (this.mode != m) {
165 | throw new JSONException(m == 'a'
166 | ? "Misplaced endArray."
167 | : "Misplaced endObject.");
168 | }
169 | this.pop(m);
170 | try {
171 | this.writer.append(c);
172 | } catch (IOException e) {
173 | // Android as of API 25 does not support this exception constructor
174 | // however we won't worry about it. If an exception is happening here
175 | // it will just throw a "Method not found" exception instead.
176 | throw new JSONException(e);
177 | }
178 | this.comma = true;
179 | return this;
180 | }
181 |
182 | /**
183 | * End an array. This method most be called to balance calls to
184 | * array
.
185 | * @return this
186 | * @throws JSONException If incorrectly nested.
187 | */
188 | public JSONWriter endArray() throws JSONException {
189 | return this.end('a', ']');
190 | }
191 |
192 | /**
193 | * End an object. This method most be called to balance calls to
194 | * object
.
195 | * @return this
196 | * @throws JSONException If incorrectly nested.
197 | */
198 | public JSONWriter endObject() throws JSONException {
199 | return this.end('k', '}');
200 | }
201 |
202 | /**
203 | * Append a key. The key will be associated with the next value. In an
204 | * object, every value must be preceded by a key.
205 | * @param string A key string.
206 | * @return this
207 | * @throws JSONException If the key is out of place. For example, keys
208 | * do not belong in arrays or if the key is null.
209 | */
210 | public JSONWriter key(String string) throws JSONException {
211 | if (string == null) {
212 | throw new JSONException("Null key.");
213 | }
214 | if (this.mode == 'k') {
215 | try {
216 | JSONObject topObject = this.stack[this.top - 1];
217 | // don't use the built in putOnce method to maintain Android support
218 | if(topObject.has(string)) {
219 | throw new JSONException("Duplicate key \"" + string + "\"");
220 | }
221 | topObject.put(string, true);
222 | if (this.comma) {
223 | this.writer.append(',');
224 | }
225 | this.writer.append(JSONObject.quote(string));
226 | this.writer.append(':');
227 | this.comma = false;
228 | this.mode = 'o';
229 | return this;
230 | } catch (IOException e) {
231 | // Android as of API 25 does not support this exception constructor
232 | // however we won't worry about it. If an exception is happening here
233 | // it will just throw a "Method not found" exception instead.
234 | throw new JSONException(e);
235 | }
236 | }
237 | throw new JSONException("Misplaced key.");
238 | }
239 |
240 |
241 | /**
242 | * Begin appending a new object. All keys and values until the balancing
243 | * endObject
will be appended to this object. The
244 | * endObject
method must be called to mark the object's end.
245 | * @return this
246 | * @throws JSONException If the nesting is too deep, or if the object is
247 | * started in the wrong place (for example as a key or after the end of the
248 | * outermost array or object).
249 | */
250 | public JSONWriter object() throws JSONException {
251 | if (this.mode == 'i') {
252 | this.mode = 'o';
253 | }
254 | if (this.mode == 'o' || this.mode == 'a') {
255 | this.append("{");
256 | this.push(new JSONObject());
257 | this.comma = false;
258 | return this;
259 | }
260 | throw new JSONException("Misplaced object.");
261 |
262 | }
263 |
264 |
265 | /**
266 | * Pop an array or object scope.
267 | * @param c The scope to close.
268 | * @throws JSONException If nesting is wrong.
269 | */
270 | private void pop(char c) throws JSONException {
271 | if (this.top <= 0) {
272 | throw new JSONException("Nesting error.");
273 | }
274 | char m = this.stack[this.top - 1] == null ? 'a' : 'k';
275 | if (m != c) {
276 | throw new JSONException("Nesting error.");
277 | }
278 | this.top -= 1;
279 | this.mode = this.top == 0
280 | ? 'd'
281 | : this.stack[this.top - 1] == null
282 | ? 'a'
283 | : 'k';
284 | }
285 |
286 | /**
287 | * Push an array or object scope.
288 | * @param jo The scope to open.
289 | * @throws JSONException If nesting is too deep.
290 | */
291 | private void push(JSONObject jo) throws JSONException {
292 | if (this.top >= maxdepth) {
293 | throw new JSONException("Nesting too deep.");
294 | }
295 | this.stack[this.top] = jo;
296 | this.mode = jo == null ? 'a' : 'k';
297 | this.top += 1;
298 | }
299 |
300 | /**
301 | * Make a JSON text of an Object value. If the object has an
302 | * value.toJSONString() method, then that method will be used to produce the
303 | * JSON text. The method is required to produce a strictly conforming text.
304 | * If the object does not contain a toJSONString method (which is the most
305 | * common case), then a text will be produced by other means. If the value
306 | * is an array or Collection, then a JSONArray will be made from it and its
307 | * toJSONString method will be called. If the value is a MAP, then a
308 | * JSONObject will be made from it and its toJSONString method will be
309 | * called. Otherwise, the value's toString method will be called, and the
310 | * result will be quoted.
311 | *
312 | *
313 | * Warning: This method assumes that the data structure is acyclical.
314 | *
315 | * @param value
316 | * The value to be serialized.
317 | * @return a printable, displayable, transmittable representation of the
318 | * object, beginning with Parsed Into JSON Converted Into ISO{
(left
319 | * brace) and ending with }
(right
320 | * brace).
321 | * @throws JSONException
322 | * If the value is or contains an invalid number.
323 | */
324 | public static String valueToString(Object value) throws JSONException {
325 | if (value == null || value.equals(null)) {
326 | return "null";
327 | }
328 | if (value instanceof JSONString) {
329 | Object object;
330 | try {
331 | object = ((JSONString) value).toJSONString();
332 | } catch (Exception e) {
333 | throw new JSONException(e);
334 | }
335 | if (object instanceof String) {
336 | return (String) object;
337 | }
338 | throw new JSONException("Bad value from toJSONString: " + object);
339 | }
340 | if (value instanceof Number) {
341 | // not all Numbers may match actual JSON Numbers. i.e. Fractions or Complex
342 | final String numberAsString = JSONObject.numberToString((Number) value);
343 | try {
344 | // Use the BigDecimal constructor for it's parser to validate the format.
345 | @SuppressWarnings("unused")
346 | BigDecimal unused = new BigDecimal(numberAsString);
347 | // Close enough to a JSON number that we will return it unquoted
348 | return numberAsString;
349 | } catch (NumberFormatException ex){
350 | // The Number value is not a valid JSON number.
351 | // Instead we will quote it as a string
352 | return JSONObject.quote(numberAsString);
353 | }
354 | }
355 | if (value instanceof Boolean || value instanceof JSONObject
356 | || value instanceof JSONArray) {
357 | return value.toString();
358 | }
359 | if (value instanceof Map) {
360 | Map, ?> map = (Map, ?>) value;
361 | return new JSONObject(map).toString();
362 | }
363 | if (value instanceof Collection) {
364 | Collection> coll = (Collection>) value;
365 | return new JSONArray(coll).toString();
366 | }
367 | if (value.getClass().isArray()) {
368 | return new JSONArray(value).toString();
369 | }
370 | if(value instanceof Enum>){
371 | return JSONObject.quote(((Enum>)value).name());
372 | }
373 | return JSONObject.quote(value.toString());
374 | }
375 |
376 | /**
377 | * Append either the value true
or the value
378 | * false
.
379 | * @param b A boolean.
380 | * @return this
381 | * @throws JSONException
382 | */
383 | public JSONWriter value(boolean b) throws JSONException {
384 | return this.append(b ? "true" : "false");
385 | }
386 |
387 | /**
388 | * Append a double value.
389 | * @param d A double.
390 | * @return this
391 | * @throws JSONException If the number is not finite.
392 | */
393 | public JSONWriter value(double d) throws JSONException {
394 | return this.value(Double.valueOf(d));
395 | }
396 |
397 | /**
398 | * Append a long value.
399 | * @param l A long.
400 | * @return this
401 | * @throws JSONException
402 | */
403 | public JSONWriter value(long l) throws JSONException {
404 | return this.append(Long.toString(l));
405 | }
406 |
407 |
408 | /**
409 | * Append an object value.
410 | * @param object The object to append. It can be null, or a Boolean, Number,
411 | * String, JSONObject, or JSONArray, or an object that implements JSONString.
412 | * @return this
413 | * @throws JSONException If the value is out of sequence.
414 | */
415 | public JSONWriter value(Object object) throws JSONException {
416 | return this.append(valueToString(object));
417 | }
418 | }
419 |
--------------------------------------------------------------------------------
/java-version/src/org/json/Property.java:
--------------------------------------------------------------------------------
1 | package org.json;
2 |
3 | /*
4 | Copyright (c) 2002 JSON.org
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | The Software shall be used for Good, not Evil.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | SOFTWARE.
25 | */
26 |
27 | import java.util.Enumeration;
28 | import java.util.Properties;
29 |
30 | /**
31 | * Converts a Property file data into JSONObject and back.
32 | * @author JSON.org
33 | * @version 2015-05-05
34 | */
35 | public class Property {
36 | /**
37 | * Converts a property file object into a JSONObject. The property file object is a table of name value pairs.
38 | * @param properties java.util.Properties
39 | * @return JSONObject
40 | * @throws JSONException
41 | */
42 | public static JSONObject toJSONObject(java.util.Properties properties) throws JSONException {
43 | // can't use the new constructor for Android support
44 | // JSONObject jo = new JSONObject(properties == null ? 0 : properties.size());
45 | JSONObject jo = new JSONObject();
46 | if (properties != null && !properties.isEmpty()) {
47 | Enumeration> enumProperties = properties.propertyNames();
48 | while(enumProperties.hasMoreElements()) {
49 | String name = (String)enumProperties.nextElement();
50 | jo.put(name, properties.getProperty(name));
51 | }
52 | }
53 | return jo;
54 | }
55 |
56 | /**
57 | * Converts the JSONObject into a property file object.
58 | * @param jo JSONObject
59 | * @return java.util.Properties
60 | * @throws JSONException
61 | */
62 | public static Properties toProperties(JSONObject jo) throws JSONException {
63 | Properties properties = new Properties();
64 | if (jo != null) {
65 | // Don't use the new entrySet API to maintain Android support
66 | for (final String key : jo.keySet()) {
67 | Object value = jo.opt(key);
68 | if (!JSONObject.NULL.equals(value)) {
69 | properties.put(key, value.toString());
70 | }
71 | }
72 | }
73 | return properties;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/java-version/src/org/json/XML.java:
--------------------------------------------------------------------------------
1 | package org.json;
2 |
3 | /*
4 | Copyright (c) 2015 JSON.org
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | The Software shall be used for Good, not Evil.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | SOFTWARE.
25 | */
26 |
27 | import java.io.Reader;
28 | import java.io.StringReader;
29 | import java.util.Iterator;
30 |
31 | /**
32 | * This provides static methods to convert an XML text into a JSONObject, and to
33 | * covert a JSONObject into an XML text.
34 | *
35 | * @author JSON.org
36 | * @version 2016-08-10
37 | */
38 | public class XML {
39 | /** The Character '&'. */
40 | public static final Character AMP = '&';
41 |
42 | /** The Character '''. */
43 | public static final Character APOS = '\'';
44 |
45 | /** The Character '!'. */
46 | public static final Character BANG = '!';
47 |
48 | /** The Character '='. */
49 | public static final Character EQ = '=';
50 |
51 | /** The Character '>'. */
52 | public static final Character GT = '>';
53 |
54 | /** The Character '<'. */
55 | public static final Character LT = '<';
56 |
57 | /** The Character '?'. */
58 | public static final Character QUEST = '?';
59 |
60 | /** The Character '"'. */
61 | public static final Character QUOT = '"';
62 |
63 | /** The Character '/'. */
64 | public static final Character SLASH = '/';
65 |
66 | /**
67 | * Creates an iterator for navigating Code Points in a string instead of
68 | * characters. Once Java7 support is dropped, this can be replaced with
69 | *
70 | * string.codePoints()
71 | *
72 | * which is available in Java8 and above.
73 | *
74 | * @see http://stackoverflow.com/a/21791059/6030888
76 | */
77 | private static Iterable
110 | * & (ampersand) is replaced by &
111 | * < (less than) is replaced by <
112 | * > (greater than) is replaced by >
113 | * " (double quote) is replaced by "
114 | * ' (single quote / apostrophe) is replaced by '
115 | *
116 | *
117 | * @param string
118 | * The string to be escaped.
119 | * @return The escaped string.
120 | */
121 | public static String escape(String string) {
122 | StringBuilder sb = new StringBuilder(string.length());
123 | for (final int cp : codePointIterator(string)) {
124 | switch (cp) {
125 | case '&':
126 | sb.append("&");
127 | break;
128 | case '<':
129 | sb.append("<");
130 | break;
131 | case '>':
132 | sb.append(">");
133 | break;
134 | case '"':
135 | sb.append(""");
136 | break;
137 | case '\'':
138 | sb.append("'");
139 | break;
140 | default:
141 | if (mustEscape(cp)) {
142 | sb.append("");
143 | sb.append(Integer.toHexString(cp));
144 | sb.append(';');
145 | } else {
146 | sb.appendCodePoint(cp);
147 | }
148 | }
149 | }
150 | return sb.toString();
151 | }
152 |
153 | /**
154 | * @param cp code point to test
155 | * @return true if the code point is not valid for an XML
156 | */
157 | private static boolean mustEscape(int cp) {
158 | /* Valid range from https://www.w3.org/TR/REC-xml/#charsets
159 | *
160 | * #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
161 | *
162 | * any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
163 | */
164 | // isISOControl is true when (cp >= 0 && cp <= 0x1F) || (cp >= 0x7F && cp <= 0x9F)
165 | // all ISO control characters are out of range except tabs and new lines
166 | return (Character.isISOControl(cp)
167 | && cp != 0x9
168 | && cp != 0xA
169 | && cp != 0xD
170 | ) || !(
171 | // valid the range of acceptable characters that aren't control
172 | (cp >= 0x20 && cp <= 0xD7FF)
173 | || (cp >= 0xE000 && cp <= 0xFFFD)
174 | || (cp >= 0x10000 && cp <= 0x10FFFF)
175 | )
176 | ;
177 | }
178 |
179 | /**
180 | * Removes XML escapes from the string.
181 | *
182 | * @param string
183 | * string to remove escapes from
184 | * @return string with converted entities
185 | */
186 | public static String unescape(String string) {
187 | StringBuilder sb = new StringBuilder(string.length());
188 | for (int i = 0, length = string.length(); i < length; i++) {
189 | char c = string.charAt(i);
190 | if (c == '&') {
191 | final int semic = string.indexOf(';', i);
192 | if (semic > i) {
193 | final String entity = string.substring(i + 1, semic);
194 | sb.append(XMLTokener.unescapeEntity(entity));
195 | // skip past the entity we just parsed.
196 | i += entity.length() + 1;
197 | } else {
198 | // this shouldn't happen in most cases since the parser
199 | // errors on unclosed entries.
200 | sb.append(c);
201 | }
202 | } else {
203 | // not part of an entity
204 | sb.append(c);
205 | }
206 | }
207 | return sb.toString();
208 | }
209 |
210 | /**
211 | * Throw an exception if the string contains whitespace. Whitespace is not
212 | * allowed in tagNames and attributes.
213 | *
214 | * @param string
215 | * A string.
216 | * @throws JSONException Thrown if the string contains whitespace or is empty.
217 | */
218 | public static void noSpace(String string) throws JSONException {
219 | int i, length = string.length();
220 | if (length == 0) {
221 | throw new JSONException("Empty string.");
222 | }
223 | for (i = 0; i < length; i += 1) {
224 | if (Character.isWhitespace(string.charAt(i))) {
225 | throw new JSONException("'" + string
226 | + "' contains a space character.");
227 | }
228 | }
229 | }
230 |
231 | /**
232 | * Scan the content following the named tag, attaching it to the context.
233 | *
234 | * @param x
235 | * The XMLTokener containing the source string.
236 | * @param context
237 | * The JSONObject that will include the new material.
238 | * @param name
239 | * The tag name.
240 | * @return true if the close tag is processed.
241 | * @throws JSONException
242 | */
243 | private static boolean parse(XMLTokener x, JSONObject context, String name, boolean keepStrings)
244 | throws JSONException {
245 | char c;
246 | int i;
247 | JSONObject jsonobject = null;
248 | String string;
249 | String tagName;
250 | Object token;
251 |
252 | // Test for and skip past these forms:
253 | //
254 | //
255 | //
256 | // ... ?>
257 | // Report errors for these forms:
258 | // <>
259 | // <=
260 | // <<
261 |
262 | token = x.nextToken();
263 |
264 | // ");
271 | return false;
272 | }
273 | x.back();
274 | } else if (c == '[') {
275 | token = x.nextToken();
276 | if ("CDATA".equals(token)) {
277 | if (x.next() == '[') {
278 | string = x.nextCDATA();
279 | if (string.length() > 0) {
280 | context.accumulate("content", string);
281 | }
282 | return false;
283 | }
284 | }
285 | throw x.syntaxError("Expected 'CDATA['");
286 | }
287 | i = 1;
288 | do {
289 | token = x.nextMeta();
290 | if (token == null) {
291 | throw x.syntaxError("Missing '>' after ' 0);
298 | return false;
299 | } else if (token == QUEST) {
300 |
301 | //
302 | x.skipPast("?>");
303 | return false;
304 | } else if (token == SLASH) {
305 |
306 | // Close tag
307 |
308 | token = x.nextToken();
309 | if (name == null) {
310 | throw x.syntaxError("Mismatched close tag " + token);
311 | }
312 | if (!token.equals(name)) {
313 | throw x.syntaxError("Mismatched " + name + " and " + token);
314 | }
315 | if (x.nextToken() != GT) {
316 | throw x.syntaxError("Misshaped close tag");
317 | }
318 | return true;
319 |
320 | } else if (token instanceof Character) {
321 | throw x.syntaxError("Misshaped tag");
322 |
323 | // Open tag <
324 |
325 | } else {
326 | tagName = (String) token;
327 | token = null;
328 | jsonobject = new JSONObject();
329 | for (;;) {
330 | if (token == null) {
331 | token = x.nextToken();
332 | }
333 | // attribute = value
334 | if (token instanceof String) {
335 | string = (String) token;
336 | token = x.nextToken();
337 | if (token == EQ) {
338 | token = x.nextToken();
339 | if (!(token instanceof String)) {
340 | throw x.syntaxError("Missing value");
341 | }
342 | jsonobject.accumulate(string,
343 | keepStrings ? ((String)token) : stringToValue((String) token));
344 | token = null;
345 | } else {
346 | jsonobject.accumulate(string, "");
347 | }
348 |
349 |
350 | } else if (token == SLASH) {
351 | // Empty tag <.../>
352 | if (x.nextToken() != GT) {
353 | throw x.syntaxError("Misshaped tag");
354 | }
355 | if (jsonobject.length() > 0) {
356 | context.accumulate(tagName, jsonobject);
357 | } else {
358 | context.accumulate(tagName, "");
359 | }
360 | return false;
361 |
362 | } else if (token == GT) {
363 | // Content, between <...> and
364 | for (;;) {
365 | token = x.nextContent();
366 | if (token == null) {
367 | if (tagName != null) {
368 | throw x.syntaxError("Unclosed tag " + tagName);
369 | }
370 | return false;
371 | } else if (token instanceof String) {
372 | string = (String) token;
373 | if (string.length() > 0) {
374 | jsonobject.accumulate("content",
375 | keepStrings ? string : stringToValue(string));
376 | }
377 |
378 | } else if (token == LT) {
379 | // Nested element
380 | if (parse(x, jsonobject, tagName,keepStrings)) {
381 | if (jsonobject.length() == 0) {
382 | context.accumulate(tagName, "");
383 | } else if (jsonobject.length() == 1
384 | && jsonobject.opt("content") != null) {
385 | context.accumulate(tagName,
386 | jsonobject.opt("content"));
387 | } else {
388 | context.accumulate(tagName, jsonobject);
389 | }
390 | return false;
391 | }
392 | }
393 | }
394 | } else {
395 | throw x.syntaxError("Misshaped tag");
396 | }
397 | }
398 | }
399 | }
400 |
401 | /**
402 | * This method is the same as {@link JSONObject#stringToValue(String)}.
403 | *
404 | * @param string String to convert
405 | * @return JSON value of this string or the string
406 | */
407 | // To maintain compatibility with the Android API, this method is a direct copy of
408 | // the one in JSONObject. Changes made here should be reflected there.
409 | public static Object stringToValue(String string) {
410 | if (string.equals("")) {
411 | return string;
412 | }
413 | if (string.equalsIgnoreCase("true")) {
414 | return Boolean.TRUE;
415 | }
416 | if (string.equalsIgnoreCase("false")) {
417 | return Boolean.FALSE;
418 | }
419 | if (string.equalsIgnoreCase("null")) {
420 | return JSONObject.NULL;
421 | }
422 |
423 | /*
424 | * If it might be a number, try converting it. If a number cannot be
425 | * produced, then the value will just be a string.
426 | */
427 |
428 | char initial = string.charAt(0);
429 | if ((initial >= '0' && initial <= '9') || initial == '-') {
430 | try {
431 | // if we want full Big Number support this block can be replaced with:
432 | // return stringToNumber(string);
433 | if (string.indexOf('.') > -1 || string.indexOf('e') > -1
434 | || string.indexOf('E') > -1 || "-0".equals(string)) {
435 | Double d = Double.valueOf(string);
436 | if (!d.isInfinite() && !d.isNaN()) {
437 | return d;
438 | }
439 | } else {
440 | Long myLong = Long.valueOf(string);
441 | if (string.equals(myLong.toString())) {
442 | if (myLong.longValue() == myLong.intValue()) {
443 | return Integer.valueOf(myLong.intValue());
444 | }
445 | return myLong;
446 | }
447 | }
448 | } catch (Exception ignore) {
449 | }
450 | }
451 | return string;
452 | }
453 |
454 | /**
455 | * Convert a well-formed (but not necessarily valid) XML string into a
456 | * JSONObject. Some information may be lost in this transformation because
457 | * JSON is a data format and XML is a document format. XML uses elements,
458 | * attributes, and content text, while JSON uses unordered collections of
459 | * name/value pairs and arrays of values. JSON does not does not like to
460 | * distinguish between elements and attributes. Sequences of similar
461 | * elements are represented as JSONArrays. Content text may be placed in a
462 | * "content" member. Comments, prologs, DTDs, and <[ [ ]]>
463 | * are ignored.
464 | *
465 | * @param string
466 | * The source string.
467 | * @return A JSONObject containing the structured data from the XML string.
468 | * @throws JSONException Thrown if there is an errors while parsing the string
469 | */
470 | public static JSONObject toJSONObject(String string) throws JSONException {
471 | return toJSONObject(string, false);
472 | }
473 |
474 | /**
475 | * Convert a well-formed (but not necessarily valid) XML into a
476 | * JSONObject. Some information may be lost in this transformation because
477 | * JSON is a data format and XML is a document format. XML uses elements,
478 | * attributes, and content text, while JSON uses unordered collections of
479 | * name/value pairs and arrays of values. JSON does not does not like to
480 | * distinguish between elements and attributes. Sequences of similar
481 | * elements are represented as JSONArrays. Content text may be placed in a
482 | * "content" member. Comments, prologs, DTDs, and <[ [ ]]>
483 | * are ignored.
484 | *
485 | * @param reader The XML source reader.
486 | * @return A JSONObject containing the structured data from the XML string.
487 | * @throws JSONException Thrown if there is an errors while parsing the string
488 | */
489 | public static JSONObject toJSONObject(Reader reader) throws JSONException {
490 | return toJSONObject(reader, false);
491 | }
492 |
493 | /**
494 | * Convert a well-formed (but not necessarily valid) XML into a
495 | * JSONObject. Some information may be lost in this transformation because
496 | * JSON is a data format and XML is a document format. XML uses elements,
497 | * attributes, and content text, while JSON uses unordered collections of
498 | * name/value pairs and arrays of values. JSON does not does not like to
499 | * distinguish between elements and attributes. Sequences of similar
500 | * elements are represented as JSONArrays. Content text may be placed in a
501 | * "content" member. Comments, prologs, DTDs, and <[ [ ]]>
502 | * are ignored.
503 | *
504 | * All values are converted as strings, for 1, 01, 29.0 will not be coerced to
505 | * numbers but will instead be the exact value as seen in the XML document.
506 | *
507 | * @param reader The XML source reader.
508 | * @param keepStrings If true, then values will not be coerced into boolean
509 | * or numeric values and will instead be left as strings
510 | * @return A JSONObject containing the structured data from the XML string.
511 | * @throws JSONException Thrown if there is an errors while parsing the string
512 | */
513 | public static JSONObject toJSONObject(Reader reader, boolean keepStrings) throws JSONException {
514 | JSONObject jo = new JSONObject();
515 | XMLTokener x = new XMLTokener(reader);
516 | while (x.more()) {
517 | x.skipPast("<");
518 | if(x.more()) {
519 | parse(x, jo, null, keepStrings);
520 | }
521 | }
522 | return jo;
523 | }
524 |
525 | /**
526 | * Convert a well-formed (but not necessarily valid) XML string into a
527 | * JSONObject. Some information may be lost in this transformation because
528 | * JSON is a data format and XML is a document format. XML uses elements,
529 | * attributes, and content text, while JSON uses unordered collections of
530 | * name/value pairs and arrays of values. JSON does not does not like to
531 | * distinguish between elements and attributes. Sequences of similar
532 | * elements are represented as JSONArrays. Content text may be placed in a
533 | * "content" member. Comments, prologs, DTDs, and <[ [ ]]>
534 | * are ignored.
535 | *
536 | * All values are converted as strings, for 1, 01, 29.0 will not be coerced to
537 | * numbers but will instead be the exact value as seen in the XML document.
538 | *
539 | * @param string
540 | * The source string.
541 | * @param keepStrings If true, then values will not be coerced into boolean
542 | * or numeric values and will instead be left as strings
543 | * @return A JSONObject containing the structured data from the XML string.
544 | * @throws JSONException Thrown if there is an errors while parsing the string
545 | */
546 | public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException {
547 | return toJSONObject(new StringReader(string), keepStrings);
548 | }
549 |
550 | /**
551 | * Convert a JSONObject into a well-formed, element-normal XML string.
552 | *
553 | * @param object
554 | * A JSONObject.
555 | * @return A string.
556 | * @throws JSONException Thrown if there is an error parsing the string
557 | */
558 | public static String toString(Object object) throws JSONException {
559 | return toString(object, null);
560 | }
561 |
562 | /**
563 | * Convert a JSONObject into a well-formed, element-normal XML string.
564 | *
565 | * @param object
566 | * A JSONObject.
567 | * @param tagName
568 | * The optional name of the enclosing tag.
569 | * @return A string.
570 | * @throws JSONException Thrown if there is an error parsing the string
571 | */
572 | public static String toString(final Object object, final String tagName)
573 | throws JSONException {
574 | StringBuilder sb = new StringBuilder();
575 | JSONArray ja;
576 | JSONObject jo;
577 | String string;
578 |
579 | if (object instanceof JSONObject) {
580 |
581 | // Emit ]]>
.
71 | * @throws JSONException If the ]]>
is not found.
72 | */
73 | public String nextCDATA() throws JSONException {
74 | char c;
75 | int i;
76 | StringBuilder sb = new StringBuilder();
77 | while (more()) {
78 | c = next();
79 | sb.append(c);
80 | i = sb.length() - 3;
81 | if (i >= 0 && sb.charAt(i) == ']' &&
82 | sb.charAt(i + 1) == ']' && sb.charAt(i + 2) == '>') {
83 | sb.setLength(i);
84 | return sb.toString();
85 | }
86 | }
87 | throw syntaxError("Unclosed CDATA");
88 | }
89 |
90 |
91 | /**
92 | * Get the next XML outer token, trimming whitespace. There are two kinds
93 | * of tokens: the '<' character which begins a markup tag, and the content
94 | * text between markup tags.
95 | *
96 | * @return A string, or a '<' Character, or null if there is no more
97 | * source text.
98 | * @throws JSONException
99 | */
100 | public Object nextContent() throws JSONException {
101 | char c;
102 | StringBuilder sb;
103 | do {
104 | c = next();
105 | } while (Character.isWhitespace(c));
106 | if (c == 0) {
107 | return null;
108 | }
109 | if (c == '<') {
110 | return XML.LT;
111 | }
112 | sb = new StringBuilder();
113 | for (;;) {
114 | if (c == 0) {
115 | return sb.toString().trim();
116 | }
117 | if (c == '<') {
118 | back();
119 | return sb.toString().trim();
120 | }
121 | if (c == '&') {
122 | sb.append(nextEntity(c));
123 | } else {
124 | sb.append(c);
125 | }
126 | c = next();
127 | }
128 | }
129 |
130 |
131 | /**
132 | * Return the next entity. These entities are translated to Characters:
133 | * & ' > < "
.
134 | * @param ampersand An ampersand character.
135 | * @return A Character or an entity String if the entity is not recognized.
136 | * @throws JSONException If missing ';' in XML entity.
137 | */
138 | public Object nextEntity(char ampersand) throws JSONException {
139 | StringBuilder sb = new StringBuilder();
140 | for (;;) {
141 | char c = next();
142 | if (Character.isLetterOrDigit(c) || c == '#') {
143 | sb.append(Character.toLowerCase(c));
144 | } else if (c == ';') {
145 | break;
146 | } else {
147 | throw syntaxError("Missing ';' in XML entity: &" + sb);
148 | }
149 | }
150 | String string = sb.toString();
151 | return unescapeEntity(string);
152 | }
153 |
154 | /**
155 | * Unescapes an XML entity encoding;
156 | * @param e entity (only the actual entity value, not the preceding & or ending ;
157 | * @return
158 | */
159 | static String unescapeEntity(String e) {
160 | // validate
161 | if (e == null || e.isEmpty()) {
162 | return "";
163 | }
164 | // if our entity is an encoded unicode point, parse it.
165 | if (e.charAt(0) == '#') {
166 | int cp;
167 | if (e.charAt(1) == 'x') {
168 | // hex encoded unicode
169 | cp = Integer.parseInt(e.substring(2), 16);
170 | } else {
171 | // decimal encoded unicode
172 | cp = Integer.parseInt(e.substring(1));
173 | }
174 | return new String(new int[] {cp},0,1);
175 | }
176 | Character knownEntity = entity.get(e);
177 | if(knownEntity==null) {
178 | // we don't know the entity so keep it encoded
179 | return '&' + e + ';';
180 | }
181 | return knownEntity.toString();
182 | }
183 |
184 |
185 | /**
186 | * Returns the next XML meta token. This is used for skipping over
187 | * and ...?> structures.
188 | * @return Syntax characters (< > / = ! ?
) are returned as
189 | * Character, and strings and names are returned as Boolean. We don't care
190 | * what the values actually are.
191 | * @throws JSONException If a string is not properly closed or if the XML
192 | * is badly structured.
193 | */
194 | public Object nextMeta() throws JSONException {
195 | char c;
196 | char q;
197 | do {
198 | c = next();
199 | } while (Character.isWhitespace(c));
200 | switch (c) {
201 | case 0:
202 | throw syntaxError("Misshaped meta tag");
203 | case '<':
204 | return XML.LT;
205 | case '>':
206 | return XML.GT;
207 | case '/':
208 | return XML.SLASH;
209 | case '=':
210 | return XML.EQ;
211 | case '!':
212 | return XML.BANG;
213 | case '?':
214 | return XML.QUEST;
215 | case '"':
216 | case '\'':
217 | q = c;
218 | for (;;) {
219 | c = next();
220 | if (c == 0) {
221 | throw syntaxError("Unterminated string");
222 | }
223 | if (c == q) {
224 | return Boolean.TRUE;
225 | }
226 | }
227 | default:
228 | for (;;) {
229 | c = next();
230 | if (Character.isWhitespace(c)) {
231 | return Boolean.TRUE;
232 | }
233 | switch (c) {
234 | case 0:
235 | case '<':
236 | case '>':
237 | case '/':
238 | case '=':
239 | case '!':
240 | case '?':
241 | case '"':
242 | case '\'':
243 | back();
244 | return Boolean.TRUE;
245 | }
246 | }
247 | }
248 | }
249 |
250 |
251 | /**
252 | * Get the next XML Token. These tokens are found inside of angle
253 | * brackets. It may be one of these characters: / > = ! ?
or it
254 | * may be a string wrapped in single quotes or double quotes, or it may be a
255 | * name.
256 | * @return a String or a Character.
257 | * @throws JSONException If the XML is not well formed.
258 | */
259 | public Object nextToken() throws JSONException {
260 | char c;
261 | char q;
262 | StringBuilder sb;
263 | do {
264 | c = next();
265 | } while (Character.isWhitespace(c));
266 | switch (c) {
267 | case 0:
268 | throw syntaxError("Misshaped element");
269 | case '<':
270 | throw syntaxError("Misplaced '<'");
271 | case '>':
272 | return XML.GT;
273 | case '/':
274 | return XML.SLASH;
275 | case '=':
276 | return XML.EQ;
277 | case '!':
278 | return XML.BANG;
279 | case '?':
280 | return XML.QUEST;
281 |
282 | // Quoted string
283 |
284 | case '"':
285 | case '\'':
286 | q = c;
287 | sb = new StringBuilder();
288 | for (;;) {
289 | c = next();
290 | if (c == 0) {
291 | throw syntaxError("Unterminated string");
292 | }
293 | if (c == q) {
294 | return sb.toString();
295 | }
296 | if (c == '&') {
297 | sb.append(nextEntity(c));
298 | } else {
299 | sb.append(c);
300 | }
301 | }
302 | default:
303 |
304 | // Name
305 |
306 | sb = new StringBuilder();
307 | for (;;) {
308 | sb.append(c);
309 | c = next();
310 | if (Character.isWhitespace(c)) {
311 | return sb.toString();
312 | }
313 | switch (c) {
314 | case 0:
315 | return sb.toString();
316 | case '>':
317 | case '/':
318 | case '=':
319 | case '!':
320 | case '?':
321 | case '[':
322 | case ']':
323 | back();
324 | return sb.toString();
325 | case '<':
326 | case '"':
327 | case '\'':
328 | throw syntaxError("Bad character in a name");
329 | }
330 | }
331 | }
332 | }
333 |
334 |
335 | /**
336 | * Skip characters until past the requested string.
337 | * If it is not found, we are left at the end of the source with a result of false.
338 | * @param to A string to skip past.
339 | */
340 | // The Android implementation of JSONTokener has a public method of public void skipPast(String to)
341 | // even though ours does not have that method, to have API compatibility, our method in the subclass
342 | // should match.
343 | public void skipPast(String to) {
344 | boolean b;
345 | char c;
346 | int i;
347 | int j;
348 | int offset = 0;
349 | int length = to.length();
350 | char[] circle = new char[length];
351 |
352 | /*
353 | * First fill the circle buffer with as many characters as are in the
354 | * to string. If we reach an early end, bail.
355 | */
356 |
357 | for (i = 0; i < length; i += 1) {
358 | c = next();
359 | if (c == 0) {
360 | return;
361 | }
362 | circle[i] = c;
363 | }
364 |
365 | /* We will loop, possibly for all of the remaining characters. */
366 |
367 | for (;;) {
368 | j = offset;
369 | b = true;
370 |
371 | /* Compare the circle buffer with the to string. */
372 |
373 | for (i = 0; i < length; i += 1) {
374 | if (circle[j] != to.charAt(i)) {
375 | b = false;
376 | break;
377 | }
378 | j += 1;
379 | if (j >= length) {
380 | j -= length;
381 | }
382 | }
383 |
384 | /* If we exit the loop with b intact, then victory is ours. */
385 |
386 | if (b) {
387 | return;
388 | }
389 |
390 | /* Get the next character. If there isn't one, then defeat is ours. */
391 |
392 | c = next();
393 | if (c == 0) {
394 | return;
395 | }
396 | /*
397 | * Shove the character in the circle buffer and advance the
398 | * circle offset. The offset is mod n.
399 | */
400 | circle[offset] = c;
401 | offset += 1;
402 | if (offset >= length) {
403 | offset -= length;
404 | }
405 | }
406 | }
407 | }
408 |
--------------------------------------------------------------------------------
/java-version/src/test/Test.java:
--------------------------------------------------------------------------------
1 | package test;
2 |
3 | import java.io.IOException;
4 |
5 | import org.json.JSONArray;
6 | import org.json.JSONException;
7 | import org.json.JSONObject;
8 |
9 | import com.bgw.translator.MessageTranslator;
10 |
11 | public class Test {
12 | public static void main(String[] args) throws IOException {
13 | String configStr = "{\"f41\":{\"format\":\"%-8s\", \"variable\":\"card_acceptor_terminal\", \"options\":\"\", \"field_length\":\"8\", \"type\":\"STRING\"},\"f63\":{\"format\":\"%-32s%-30s%-50s%-18s\", \"variable\":\"locket_code, locket_name, locket_address, locket_phone\", \"options\":\"\", \"field_length\":\"130\", \"type\":\"LLLVAR\"},\"f32\":{\"format\":\"%-11s\", \"variable\":\"acq_institution_code\", \"options\":\"\", \"field_length\":\"11\", \"type\":\"LLVAR\"},\"f42\":{\"format\":\"%15s\", \"variable\":\"acceptor_identification_code\", \"options\":\"\", \"field_length\":\"15\", \"type\":\"STRING\"},\"f121\":{\"format\":\"%-32s\", \"variable\":\"payment_reference\", \"options\":\"\", \"field_length\":\"32\", \"type\":\"LLLVAR\"},\"f12\":{\"format\":\"%-6s\", \"variable\":\"local_time\", \"options\":\"\", \"field_length\":\"6\", \"type\":\"STRING\"},\"f120\":{\"format\":\"%-20s\", \"variable\":\"product_code\", \"options\":\"\", \"field_length\":\"20\", \"type\":\"LLLVAR\"},\"f11\":{\"format\":\"%06d\", \"variable\":\"stan\", \"options\":\"\", \"field_length\":\"6\", \"type\":\"NUMERIC\"},\"f33\":{\"format\":\"%-11s\", \"variable\":\"fwd_institution_code\", \"options\":\"\", \"field_length\":\"11\", \"type\":\"LLVAR\"},\"f13\":{\"format\":\"%-4s\", \"variable\":\"local_date\", \"options\":\"\", \"field_length\":\"4\", \"type\":\"STRING\"},\"f49\":{\"format\":\"%03d\", \"variable\":\"transaction_currency_code\", \"options\":\"\", \"field_length\":\"3\", \"type\":\"NUMERIC\"},\"f15\":{\"format\":\"%-4s\", \"variable\":\"settlement_date\", \"options\":\"\", \"field_length\":\"4\", \"type\":\"STRING\"},\"f37\":{\"format\":\"%012d\", \"variable\":\"reference_number\", \"options\":\"\", \"field_length\":\"12\", \"type\":\"NUMERIC\"},\"f48\":{\"format\":\"%11s%12s%01d\", \"variable\":\"meter_id, customer_id, id_selector\", \"options\":\"\", \"field_length\":\"24\", \"type\":\"LLLVAR\"},\"f2\":{\"format\":\"%-19s\", \"variable\":\"pan\", \"options\":\"\", \"field_length\":\"19\", \"type\":\"LLVAR\"},\"f18\":{\"format\":\"%04d\", \"variable\":\"merchant_type\", \"options\":\"\", \"field_length\":\"4\", \"type\":\"NUMERIC\"},\"f3\":{\"format\":\"%06d\", \"variable\":\"processing_code\", \"options\":\"\", \"field_length\":\"6\", \"type\":\"NUMERIC\"},\"f4\":{\"format\":\"%012d\", \"variable\":\"amount\", \"options\":\"\", \"field_length\":\"12\", \"type\":\"NUMERIC\"},\"f7\":{\"format\":\"%-10s\", \"variable\":\"transmission_date_time\", \"options\":\"\", \"field_length\":\"10\", \"type\":\"STRING\"},\"f127\":{\"format\":\"%-20s%-32s\", \"variable\":\"username, password\", \"options\":\"\", \"field_length\":\"52\", \"type\":\"LLLVAR\"}}";
14 |
15 | MessageTranslator mt = new MessageTranslator();
16 | String mti_id = "0210";
17 | String iso = "0200F23A400188C180060000000000000182196048200000002731 300000000000020000092513425200007213425209250926602111597 1112345 000000000072DEVALT0120090010080000014514987654321149999999911030E8597E3B2F1646505FDD6E210000090MUP210ZBE957561167FCD8506326E4AHAMDANIE LESTALUHUANI R1 00000090000000090000000011653600505151106123 0600000000000000000000000000130 ALTO Jalan Anggrek Neli Murni 02199999 02000500050001 03214987654321 052tester1 tester1 ";
18 | String iso_new = "";
19 | String xml = "";
20 | JSONObject config = new JSONObject();
21 | JSONObject json = new JSONObject();
22 |
23 |
24 | try
25 | {
26 | config = new JSONObject(configStr);
27 | json = mt.parseISO8583(iso, config);
28 | iso_new = new String(mt.buildISO8583(json, config, mti_id));
29 | xml = mt.buildXML(json, "data");
30 |
31 | System.out.println("Demonstration of conversion of ISO 8583 - JSON - XML");
32 | System.out.println("Config : ");
33 | System.out.println(config.toString());
34 | System.out.println("=============================================================");
35 |
36 | System.out.println("Original ISO 8583 : ");
37 | System.out.println("'"+iso+"'");
38 | System.out.println("Convert ISO to JSON");
39 | System.out.println("JSON : ");
40 | System.out.println(json.toString());
41 | System.out.println("=============================================================");
42 |
43 | System.out.println("Now, convert JSON to new ISO");
44 | System.out.println("New ISO 8583 : ");
45 | System.out.println("'"+iso_new+"'");
46 | System.out.println("=============================================================");
47 |
48 | System.out.println("Now, convert JSON to XML");
49 | System.out.println("XML : ");
50 | System.out.println(xml);
51 | System.out.println("=============================================================");
52 |
53 | }
54 | catch (JSONException e)
55 | {
56 | e.printStackTrace();
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/php-version/index.php:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
21 | Original ISO :
22 |
25 |
26 |
28 | JSON :
29 |
32 |
33 |
35 | New ISO :
36 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/php-version/lib/MessageTranslator.php:
--------------------------------------------------------------------------------
1 | iso_config = json_decode($iso_config, true);
14 | }
15 | $keys = array_keys($this->iso_config);
16 | if(in_array(0, $keys))
17 | {
18 | $tmp = $this->iso_config;
19 | $this->iso_config = array();
20 | foreach($tmp as $key=>$value)
21 | {
22 | $this->iso_config['f'.$value['field']] = $value;
23 | }
24 | }
25 | }
26 | function parseISO($message, $iso_config = null)
27 | {
28 | if($iso_config !== null)
29 | {
30 | $this->setConfig($iso_config);
31 | }
32 | $this->parse($message);
33 | $data = array();
34 | foreach($this->iso_config as $field_str=>$config)
35 | {
36 | $field = substr($field_str, 1);
37 | $raw_data = $this->values[$field];
38 | $variables = $config['variable'];
39 | $formats = $config['format'];
40 | $array_variable = explode(",", preg_replace('/\s+/', '', $variables));
41 | $array_format = explode("%", $formats);
42 | $offset = 0;
43 | foreach($array_variable as $idx=>$variable)
44 | {
45 | $fmt = preg_replace("/[^0-9]/", "", $array_format[$idx+1]);
46 | $len = abs($fmt * 1);
47 | $variable = trim($variable);
48 | $data[$variable] = substr($raw_data, $offset, $len);
49 | $offset += $len;
50 | }
51 | }
52 | return $data;
53 | }
54 | function buildISO($json, $iso_config = null, $mti)
55 | {
56 | if($iso_config !== null)
57 | {
58 | $this->setConfig($iso_config);
59 | }
60 | $this->setType($mti);
61 | $data = array();
62 |
63 | foreach($this->iso_config as $field_str=>$config)
64 | {
65 | $field = substr($field_str, 1);
66 | $raw_data = "";
67 | $variables = $config['variable'];
68 | $formats = $config['format'];
69 | $array_variable = explode(",", preg_replace('/\s+/', '', $variables));
70 | $array_format = explode("%", $formats);
71 | $offset = 0;
72 | foreach($array_variable as $idx=>$variable)
73 | {
74 | $fmt = $array_format[$idx+1];
75 | $len = abs($fmt * 1);
76 | $format = "%".$fmt;
77 | $variable = trim($variable);
78 | $data = @$json[$variable];
79 | if(stripos($fmt, "d") !== false)
80 | {
81 | $data = $data * 1;
82 | }
83 | $raw_data .= sprintf($format, $data);
84 | }
85 | $this->addBit($field, $raw_data);
86 | }
87 | return $this->getISO();
88 | }
89 |
90 | }
91 | ?>
--------------------------------------------------------------------------------
/php-version/lib/RoyISO8583.php:
--------------------------------------------------------------------------------
1 | array('b', 64, 0),
5 | 2 => array('an', 19, 1),
6 | 3 => array('n', 6, 0),
7 | 4 => array('n', 12, 0),
8 | 5 => array('n', 12, 0),
9 | 6 => array('n', 12, 0),
10 | 7 => array('an', 10, 0),
11 | 8 => array('n', 8, 0),
12 | 9 => array('n', 8, 0),
13 | 10 => array('n', 8, 0),
14 | 11 => array('n', 6, 0),
15 | 12 => array('n', 6, 0),
16 | 13 => array('n', 4, 0),
17 | 14 => array('n', 4, 0),
18 | 15 => array('n', 4, 0),
19 | 16 => array('n', 4, 0),
20 | 17 => array('n', 4, 0),
21 | 18 => array('n', 4, 0),
22 | 19 => array('n', 3, 0),
23 | 20 => array('n', 3, 0),
24 | 21 => array('n', 3, 0),
25 | 22 => array('n', 3, 0),
26 | 23 => array('n', 3, 0),
27 | 24 => array('n', 3, 0),
28 | 25 => array('n', 2, 0),
29 | 26 => array('n', 2, 0),
30 | 27 => array('n', 1, 0),
31 | 28 => array('n', 8, 0),
32 | 29 => array('an', 9, 0),
33 | 30 => array('n', 8, 0),
34 | 31 => array('an', 9, 0),
35 | 32 => array('n', 11, 1),
36 | 33 => array('n', 11, 1),
37 | 34 => array('an', 28, 1),
38 | 35 => array('z', 37, 1),
39 | 36 => array('n', 104, 1),
40 | 37 => array('an', 12, 0),
41 | 38 => array('an', 6, 0),
42 | 39 => array('an', 2, 0),
43 | 40 => array('an', 3, 0),
44 | 41 => array('ans', 8, 0),
45 | 42 => array('ans', 15, 0),
46 | 43 => array('ans', 40, 0),
47 | 44 => array('an', 25, 1),
48 | 45 => array('an', 76, 1),
49 | 46 => array('an', 999, 1),
50 | 47 => array('an', 999, 1),
51 | 48 => array('ans', 119, 1),
52 | 49 => array('an', 3, 0),
53 | 50 => array('an', 3, 0),
54 | 51 => array('a', 3, 0),
55 | 52 => array('an', 16, 0),
56 | 53 => array('an', 18, 0),
57 | 54 => array('an', 120, 0),
58 | 55 => array('ans', 999, 1),
59 | 56 => array('ans', 999, 1),
60 | 57 => array('ans', 999, 1),
61 | 58 => array('ans', 999, 1),
62 | 59 => array('ans', 99, 1),
63 | 60 => array('ans', 60, 1),
64 | 61 => array('ans', 99, 1),
65 | 62 => array('ans', 999, 1),
66 | 63 => array('ans', 999, 1),
67 | 64 => array('b', 16, 0),
68 | 65 => array('b', 16, 0),
69 | 66 => array('n', 1, 0),
70 | 67 => array('n', 2, 0),
71 | 68 => array('n', 3, 0),
72 | 69 => array('n', 3, 0),
73 | 70 => array('n', 3, 0),
74 | 71 => array('n', 4, 0),
75 | 72 => array('ans', 999, 1),
76 | 73 => array('n', 6, 0),
77 | 74 => array('n', 10, 0),
78 | 75 => array('n', 10, 0),
79 | 76 => array('n', 10, 0),
80 | 77 => array('n', 10, 0),
81 | 78 => array('n', 10, 0),
82 | 79 => array('n', 10, 0),
83 | 80 => array('n', 10, 0),
84 | 81 => array('n', 10, 0),
85 | 82 => array('n', 12, 0),
86 | 83 => array('n', 12, 0),
87 | 84 => array('n', 12, 0),
88 | 85 => array('n', 12, 0),
89 | 86 => array('n', 15, 0),
90 | 87 => array('an', 16, 0),
91 | 88 => array('n', 16, 0),
92 | 89 => array('n', 16, 0),
93 | 90 => array('an', 42, 0),
94 | 91 => array('an', 1, 0),
95 | 92 => array('n', 2, 0),
96 | 93 => array('n', 5, 0),
97 | 94 => array('an', 7, 0),
98 | 95 => array('an', 42, 0),
99 | 96 => array('an', 8, 0),
100 | 97 => array('an', 17, 0),
101 | 98 => array('ans', 25, 0),
102 | 99 => array('n', 11, 1),
103 | 100 => array('n', 11, 1),
104 | 101 => array('ans', 17, 0),
105 | 102 => array('ans', 28, 1),
106 | 103 => array('ans', 28, 1),
107 | 104 => array('an', 100, 1),
108 | 105 => array('ans', 999, 1),
109 | 106 => array('ans', 999, 1),
110 | 107 => array('ans', 999, 1),
111 | 108 => array('ans', 999, 1),
112 | 109 => array('ans', 999, 1),
113 | 110 => array('ans', 999, 1),
114 | 111 => array('ans', 999, 1),
115 | 112 => array('ans', 999, 1),
116 | 113 => array('n', 11, 1),
117 | 114 => array('ans', 999, 1),
118 | 115 => array('ans', 999, 1),
119 | 116 => array('ans', 999, 1),
120 | 117 => array('ans', 999, 1),
121 | 118 => array('ans', 999, 1),
122 | 119 => array('ans', 999, 1),
123 | 120 => array('ans', 999, 1),
124 | 121 => array('ans', 999, 1),
125 | 122 => array('ans', 999, 1),
126 | 123 => array('ans', 999, 1),
127 | 124 => array('ans', 255, 1),
128 | 125 => array('ans', 50, 1),
129 | 126 => array('ans', 6, 1),
130 | 127 => array('ans', 999, 1),
131 | 128 => array('b', 16, 0)
132 | );
133 |
134 | public $fields = array();
135 | public $values = array();
136 | public function addBit($bit, $value = null)
137 | {
138 | $this->fields[] = $bit*1;
139 | $this->fields = array_unique($this->fields);
140 | if($value !== null)
141 | {
142 | if($this->general_config[$bit][0] == 'n')
143 | {
144 | // numeric
145 | $val = $value*1;
146 | if($this->general_config[$bit][2] == 0)
147 | {
148 | // fix length
149 | $value = sprintf("%0".$this->general_config[$bit][1]."d", $val);
150 | }
151 | }
152 | else
153 | {
154 | // non numeric
155 | if($this->general_config[$bit][2] == 0)
156 | {
157 | // fix length
158 | $value = str_pad($value, $this->general_config[$bit][1], ' ', STR_PAD_RIGHT);
159 | }
160 | }
161 | $this->values[$bit] = $value;
162 | }
163 | else
164 | {
165 | $this->values[$bit] = null;
166 | }
167 | sort($this->fields, SORT_NUMERIC );
168 | ksort($this->values, SORT_NUMERIC );
169 | }
170 | public function addValue($bit, $value)
171 | {
172 | $this->addBit($bit, $value);
173 | }
174 | public function addData($bit, $value)
175 | {
176 | $this->addBit($bit, $value);
177 | }
178 | public $maxField = 1;
179 |
180 | public $segment1 = array(0,0);
181 | public $segment2 = array(0,0);
182 | public $segment3 = array(0,0);
183 |
184 | function getBitmap()
185 | {
186 | $tmp = sprintf("%064d", 0);
187 | $tmp2 = sprintf("%064d", 0);
188 | foreach ($this->values as $key=>$val)
189 | {
190 | if($key<65)
191 | {
192 | $tmp[$key-1] = 1;
193 | }
194 | else
195 | {
196 | $tmp[0] = 1;
197 | $tmp2[$key-65] = 1;
198 | }
199 | }
200 | $result = "";
201 | if($tmp[0]==1)
202 | {
203 | while ($tmp2!='')
204 | {
205 | $result .= base_convert(substr($tmp2, 0, 4), 2, 16);
206 | $tmp2 = substr($tmp2, 4, strlen($tmp2)-4);
207 | }
208 | }
209 | $main = "";
210 | while ($tmp!='')
211 | {
212 | $main .= base_convert(substr($tmp, 0, 4), 2, 16);
213 | $tmp = substr($tmp, 4, strlen($tmp)-4);
214 | }
215 | $this->_bitmap = strtoupper($main. $result);
216 |
217 | return $this->_bitmap;
218 | }
219 | public $type = "0000";
220 | public $valid = array('mti'=>false, 'bitmap'=>false, 'data'=>false);
221 | public function parse3($message)
222 | {
223 | // parse type and bitmap
224 | $fields = array();
225 |
226 | $this->iso = $message;
227 |
228 | $this->valid['bitmap'] = false;
229 | $inp = substr($this->iso, 4, 32);
230 | if (strlen($inp)>=16)
231 | {
232 | $primary = '';
233 | $secondary = '';
234 | for ($i=0; $i<16; $i++)
235 | {
236 | $primary .= sprintf("%04d", base_convert($inp[$i], 16, 2));
237 | }
238 | if ($primary[0]==1 && strlen($inp)>=32)
239 | {
240 | for ($i=16; $i<32; $i++)
241 | {
242 | $secondary .= sprintf("%04d", base_convert($inp[$i], 16, 2));
243 | }
244 | $this->valid['bitmap'] = true;
245 | }
246 | if ($secondary=='')
247 | {
248 | $this->valid['bitmap'] = true;
249 | }
250 | }
251 | //save to data element with ? character
252 | $tmp = $primary. $secondary;
253 | for ($i=0; $i