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 @SuppressWarnings("resource")
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 public static void writeData(final String filename, final DataTable dataTable)
173 throws IOException, TextSerializationException
174 {
175 FileWriter fw = null;
176 try
177 {
178 fw = new FileWriter(filename);
179 writeData(fw, dataTable);
180 }
181 finally
182 {
183 if (null != fw)
184 {
185 fw.close();
186 }
187 }
188 }
189
190
191
192
193
194
195
196
197 public static DataTable readData(final Reader reader) throws IOException, TextSerializationException
198 {
199 JsonReader jr = null;
200 try
201 {
202
203 jr = new JsonReader(reader);
204 jr.beginObject();
205 readName(jr, "table");
206 jr.beginObject();
207 String[] tableProperties = new String[3];
208 tableProperties[0] = readValue(jr, "id");
209 tableProperties[1] = readValue(jr, "description");
210 tableProperties[2] = readValue(jr, "class");
211 Throw.when(!tableProperties[2].endsWith("ListDataTable"), IOException.class,
212 "Currently, this method can only recreate a ListDataTable");
213
214
215 List<DataColumn<?>> columns = new ArrayList<>();
216 int index = 0;
217 readName(jr, "columns");
218 jr.beginArray();
219 while (jr.peek().equals(JsonToken.BEGIN_OBJECT))
220 {
221 String[] columnProperties = new String[4];
222 jr.beginObject();
223 columnProperties[0] = readValue(jr, "nr");
224 columnProperties[1] = readValue(jr, "id");
225 columnProperties[2] = readValue(jr, "description");
226 columnProperties[3] = readValue(jr, "type");
227 jr.endObject();
228
229 if (Integer.valueOf(columnProperties[0]).intValue() != index)
230 {
231 throw new IOException("column nr not ok");
232 }
233 String type = columnProperties[3];
234 Class<?> valueClass = Primitive.forName(type);
235 if (valueClass == null)
236 {
237 try
238 {
239 valueClass = Class.forName(type);
240 }
241 catch (ClassNotFoundException exception)
242 {
243 throw new IOException("Could not find class " + type, exception);
244 }
245 }
246 @SuppressWarnings({"rawtypes", "unchecked"})
247 DataColumn<?> column = new SimpleDataColumn(columnProperties[1], columnProperties[2], valueClass);
248 columns.add(column);
249 index++;
250 }
251 jr.endArray();
252 jr.endObject();
253
254 ListDataTable dataTable = new ListDataTable(tableProperties[0], tableProperties[1], columns);
255
256
257 TextSerializer<?>[] serializers = new TextSerializer[dataTable.getNumberOfColumns()];
258 for (int i = 0; i < dataTable.getNumberOfColumns(); i++)
259 {
260 DataColumn<?> column = dataTable.getColumns().get(i);
261 serializers[i] = TextSerializer.resolve(column.getValueType());
262 }
263
264
265 readName(jr, "data");
266 jr.beginArray();
267 while (jr.peek().equals(JsonToken.BEGIN_ARRAY))
268 {
269 Object[] values = new Object[columns.size()];
270 jr.beginArray();
271 for (int i = 0; i < dataTable.getNumberOfColumns(); i++)
272 {
273 jr.beginObject();
274 values[i] = serializers[i].deserialize(readValue(jr, "" + i));
275 jr.endObject();
276 }
277 jr.endArray();
278 dataTable.addRecord(values);
279 }
280
281
282 jr.endArray();
283 jr.endObject();
284 return dataTable;
285 }
286 finally
287 {
288 if (null != jr)
289 {
290 jr.close();
291 }
292 }
293 }
294
295
296
297
298
299
300
301
302
303 private static String readValue(final JsonReader jr, final String tag) throws IllegalFormatException, IOException
304 {
305 Throw.when(!jr.nextName().equals(tag), IllegalFormatException.class, "readValue: no %s object", tag);
306 return jr.nextString();
307 }
308
309
310
311
312
313
314
315
316 private static void readName(final JsonReader jr, final String tag) throws IllegalFormatException, IOException
317 {
318 Throw.when(!jr.nextName().equals(tag), IllegalFormatException.class, "readName: no %s object", tag);
319 }
320
321
322
323
324
325
326
327
328 public static DataTable readData(final String filename) throws IOException, TextSerializationException
329 {
330 FileReader fr = null;
331 try
332 {
333 fr = new FileReader(filename);
334 return readData(fr);
335 }
336 finally
337 {
338 if (null != fr)
339 {
340 fr.close();
341 }
342 }
343 }
344
345 }