1 package org.djutils.data.json;
2
3 import java.io.FileReader;
4 import java.io.FileWriter;
5 import java.io.IOException;
6 import java.io.Reader;
7 import java.io.Writer;
8 import java.util.ArrayList;
9 import java.util.IllegalFormatException;
10 import java.util.List;
11
12 import org.djutils.data.DataColumn;
13 import org.djutils.data.DataRecord;
14 import org.djutils.data.DataTable;
15 import org.djutils.data.ListDataTable;
16 import org.djutils.data.SimpleDataColumn;
17 import org.djutils.data.serialization.TextSerializationException;
18 import org.djutils.data.serialization.TextSerializer;
19 import org.djutils.exceptions.Throw;
20 import org.djutils.primitives.Primitive;
21
22 import com.google.gson.stream.JsonReader;
23 import com.google.gson.stream.JsonToken;
24 import com.google.gson.stream.JsonWriter;
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81 public final class JSONData
82 {
83
84
85
86 private JSONData()
87 {
88
89 }
90
91
92
93
94
95
96
97
98
99 public static void writeData(final Writer writer, final DataTable dataTable) throws IOException, TextSerializationException
100 {
101 JsonWriter jw = null;
102 try
103 {
104 jw = new JsonWriter(writer);
105 jw.setIndent(" ");
106
107
108 jw.beginObject();
109 jw.name("table").beginObject();
110 jw.name("id").value(dataTable.getId());
111 jw.name("description").value(dataTable.getDescription());
112 jw.name("class").value(dataTable.getClass().getName());
113 jw.name("columns").beginArray();
114 int index = 0;
115 for (DataColumn<?> column : dataTable.getColumns())
116 {
117 jw.beginObject();
118 jw.name("nr").value(index++);
119 jw.name("id").value(column.getId());
120 jw.name("description").value(column.getDescription());
121 jw.name("type").value(column.getValueType().getName());
122 jw.endObject();
123 }
124 jw.endArray();
125 jw.endObject();
126
127
128 TextSerializer<?>[] serializers = new TextSerializer[dataTable.getNumberOfColumns()];
129 for (int i = 0; i < dataTable.getNumberOfColumns(); i++)
130 {
131 DataColumn<?> column = dataTable.getColumns().get(i);
132 serializers[i] = TextSerializer.resolve(column.getValueType());
133 }
134
135
136 jw.name("data").beginArray();
137
138
139 for (DataRecord record : dataTable)
140 {
141 Object[] values = record.getValues();
142 jw.beginArray();
143 jw.setIndent("");
144 for (int i = 0; i < dataTable.getNumberOfColumns(); i++)
145 {
146 jw.beginObject().name(String.valueOf(i)).value(serializers[i].serialize(values[i])).endObject();
147 }
148 jw.endArray();
149 jw.setIndent(" ");
150 }
151
152
153 jw.endArray();
154 jw.endObject();
155 }
156 finally
157 {
158 if (null != jw)
159 {
160 jw.close();
161 }
162 }
163 }
164
165
166
167
168
169
170
171
172
173 public static void writeData(final String filename, final DataTable dataTable)
174 throws IOException, TextSerializationException
175 {
176 FileWriter fw = null;
177 try
178 {
179 fw = new FileWriter(filename);
180 writeData(fw, dataTable);
181 }
182 finally
183 {
184 if (null != fw)
185 {
186 fw.close();
187 }
188 }
189 }
190
191
192
193
194
195
196
197
198 public static DataTable readData(final Reader reader) throws IOException, TextSerializationException
199 {
200 JsonReader jr = null;
201 try
202 {
203
204 jr = new JsonReader(reader);
205 jr.beginObject();
206 readName(jr, "table");
207 jr.beginObject();
208 String[] tableProperties = new String[3];
209 tableProperties[0] = readValue(jr, "id");
210 tableProperties[1] = readValue(jr, "description");
211 tableProperties[2] = readValue(jr, "class");
212 Throw.when(!tableProperties[2].endsWith("ListDataTable"), IOException.class,
213 "Currently, this method can only recreate a ListDataTable");
214
215
216 List<DataColumn<?>> columns = new ArrayList<>();
217 int index = 0;
218 readName(jr, "columns");
219 jr.beginArray();
220 while (jr.peek().equals(JsonToken.BEGIN_OBJECT))
221 {
222 String[] columnProperties = new String[4];
223 jr.beginObject();
224 columnProperties[0] = readValue(jr, "nr");
225 columnProperties[1] = readValue(jr, "id");
226 columnProperties[2] = readValue(jr, "description");
227 columnProperties[3] = readValue(jr, "type");
228 jr.endObject();
229
230 if (Integer.valueOf(columnProperties[0]).intValue() != index)
231 {
232 throw new IOException("column nr not ok");
233 }
234 String type = columnProperties[3];
235 Class<?> valueClass = Primitive.forName(type);
236 if (valueClass == null)
237 {
238 try
239 {
240 valueClass = Class.forName(type);
241 }
242 catch (ClassNotFoundException exception)
243 {
244 throw new IOException("Could not find class " + type, exception);
245 }
246 }
247 @SuppressWarnings({ "rawtypes", "unchecked" })
248 DataColumn<?> column = new SimpleDataColumn(columnProperties[1], columnProperties[2], valueClass);
249 columns.add(column);
250 index++;
251 }
252 jr.endArray();
253 jr.endObject();
254
255 ListDataTablestDataTable">ListDataTable dataTable = new ListDataTable(tableProperties[0], tableProperties[1], columns);
256
257
258 TextSerializer<?>[] serializers = new TextSerializer[dataTable.getNumberOfColumns()];
259 for (int i = 0; i < dataTable.getNumberOfColumns(); i++)
260 {
261 DataColumn<?> column = dataTable.getColumns().get(i);
262 serializers[i] = TextSerializer.resolve(column.getValueType());
263 }
264
265
266 readName(jr, "data");
267 jr.beginArray();
268 while (jr.peek().equals(JsonToken.BEGIN_ARRAY))
269 {
270 Object[] values = new Object[columns.size()];
271 jr.beginArray();
272 for (int i = 0; i < dataTable.getNumberOfColumns(); i++)
273 {
274 jr.beginObject();
275 values[i] = serializers[i].deserialize(readValue(jr, "" + i));
276 jr.endObject();
277 }
278 jr.endArray();
279 dataTable.addRecord(values);
280 }
281
282
283 jr.endArray();
284 jr.endObject();
285 return dataTable;
286 }
287 finally
288 {
289 if (null != jr)
290 {
291 jr.close();
292 }
293 }
294 }
295
296
297
298
299
300
301
302
303
304
305
306 private static String readValue(final JsonReader jr, final String tag) throws IllegalFormatException, IOException
307 {
308 Throw.when(!jr.nextName().equals(tag), IllegalFormatException.class, "readValue: no %s object", tag);
309 return jr.nextString();
310 }
311
312
313
314
315
316
317
318
319
320
321 private static void readName(final JsonReader jr, final String tag) throws IllegalFormatException, IOException
322 {
323 Throw.when(!jr.nextName().equals(tag), IllegalFormatException.class, "readName: no %s object", tag);
324 }
325
326
327
328
329
330
331
332
333 public static DataTable readData(final String filename) throws IOException, TextSerializationException
334 {
335 FileReader fr = null;
336 try
337 {
338 fr = new FileReader(filename);
339 return readData(fr);
340 }
341 finally
342 {
343 if (null != fr)
344 {
345 fr.close();
346 }
347 }
348 }
349
350 }