View Javadoc
1   /*
2    * This file is part of Waarp Project (named also Waarp or GG).
3    *
4    *  Copyright (c) 2019, Waarp SAS, and individual contributors by the @author
5    *  tags. See the COPYRIGHT.txt in the distribution for a full listing of
6    * individual contributors.
7    *
8    *  All Waarp Project is free software: you can redistribute it and/or
9    * modify it under the terms of the GNU General Public License as published by
10   * the Free Software Foundation, either version 3 of the License, or (at your
11   * option) any later version.
12   *
13   * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY
14   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15   * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16   *
17   *  You should have received a copy of the GNU General Public License along with
18   * Waarp . If not, see <http://www.gnu.org/licenses/>.
19   */
20  package org.waarp.common.json;
21  
22  import com.fasterxml.jackson.core.JsonGenerator;
23  import com.fasterxml.jackson.core.JsonParseException;
24  import com.fasterxml.jackson.core.JsonParser;
25  import com.fasterxml.jackson.core.JsonProcessingException;
26  import com.fasterxml.jackson.core.type.TypeReference;
27  import com.fasterxml.jackson.databind.DeserializationFeature;
28  import com.fasterxml.jackson.databind.JsonMappingException;
29  import com.fasterxml.jackson.databind.JsonNode;
30  import com.fasterxml.jackson.databind.ObjectMapper;
31  import com.fasterxml.jackson.databind.node.ArrayNode;
32  import com.fasterxml.jackson.databind.node.ObjectNode;
33  import org.waarp.common.logging.SysErrLogger;
34  import org.waarp.common.utility.ParametersChecker;
35  
36  import java.io.File;
37  import java.io.IOException;
38  import java.util.HashMap;
39  import java.util.Map;
40  
41  /**
42   * Abstract Json Handler
43   */
44  public class JsonHandler {
45  
46    public static final TypeReference<Map<String, Object>>
47        typeReferenceMapStringObject = new TypeReference<Map<String, Object>>() {
48    };
49    /**
50     * JSON parser
51     */
52    public static final ObjectMapper mapper =
53        new ObjectMapper().configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true)
54                          .configure(
55                              JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true)
56                          .configure(
57                              DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
58                              false)
59                          .configure(JsonGenerator.Feature.ESCAPE_NON_ASCII,
60                                     true);
61  
62    protected JsonHandler() {
63    }
64  
65    /**
66     * @return an empty ObjectNode
67     */
68    public static ObjectNode createObjectNode() {
69      return mapper.createObjectNode();
70    }
71  
72    /**
73     * @return an empty ArrayNode
74     */
75    public static ArrayNode createArrayNode() {
76      return mapper.createArrayNode();
77    }
78  
79    /**
80     * Parses a string representation of a JSON object and returns an
81     * ObjectNode.
82     * JSON Processing exceptions are
83     * kept.
84     *
85     * @param value
86     *
87     * @return the objectNode or null if an error occurs
88     *
89     * @throws JsonProcessingException
90     */
91    public static ObjectNode getFromStringExc(final String value)
92        throws JsonProcessingException {
93      try {
94        return (ObjectNode) mapper.readTree(value);
95      } catch (final JsonProcessingException e) {
96        throw e;
97      } catch (final Exception e) {
98        return null;
99      }
100   }
101 
102   /**
103    * Parses a string representation of a JSON object and returns an
104    * ObjectNode,
105    * swallowing any processing
106    * exception.
107    *
108    * @param value
109    *
110    * @return the objectNode or null if an error occurs
111    */
112   public static ObjectNode getFromString(final String value) {
113     try {
114       return (ObjectNode) mapper.readTree(value);
115     } catch (final JsonProcessingException e) {
116       return null;
117     } catch (final Exception e) {
118       return null;
119     }
120   }
121 
122   /**
123    * @param file
124    *
125    * @return the jsonNode (ObjectNode or ArrayNode)
126    */
127   public static ObjectNode getFromFile(final File file) {
128     try {
129       return (ObjectNode) mapper.readTree(file);
130     } catch (final JsonProcessingException e) {
131       return null;
132     } catch (final IOException e) {
133       return null;
134     }
135   }
136 
137   /**
138    * @param value
139    * @param clasz
140    *
141    * @return the object of type clasz
142    */
143   public static <T> T getFromString(final String value, final Class<T> clasz) {
144     try {
145       return mapper.readValue(value, clasz);
146     } catch (final IOException e) {
147       return null;
148     }
149   }
150 
151   /**
152    * @param file
153    * @param clasz
154    *
155    * @return the corresponding object
156    */
157   public static Object getFromFile(final File file, final Class<?> clasz) {
158     try {
159       return mapper.readValue(file, clasz);
160     } catch (final IOException e) {
161       return null;
162     }
163   }
164 
165   /**
166    * @param object
167    *
168    * @return the Json representation of the object
169    */
170   public static String writeAsString(final Object object) {
171     try {
172       return mapper.writeValueAsString(object);
173     } catch (final JsonProcessingException e) {
174       return "{}";
175     }
176   }
177 
178   /**
179    * @param object
180    *
181    * @return the Json escaped representation of the object
182    */
183   public static String writeAsStringEscaped(final Object object) {
184     try {
185       final String temp = mapper.writeValueAsString(object);
186       return temp.replaceAll("[\\\\]+", "\\\\");
187     } catch (final JsonProcessingException e) {
188       return "{}";
189     }
190   }
191 
192   /**
193    * Unespace source string before analyzing it as Json
194    *
195    * @param source
196    *
197    * @return the unescaped source
198    */
199   public static String unEscape(final String source) {
200     return source.replace("\\", "");
201   }
202 
203   /**
204    * @param object
205    * @param file
206    *
207    * @return True if correctly written
208    */
209   public static boolean writeAsFile(final Object object, final File file) {
210     try {
211       mapper.writeValue(file, object);
212       return true;
213     } catch (final IOException e) {
214       return false;
215     }
216   }
217 
218   /**
219    * @param object
220    *
221    * @return the Json representation of the object in Pretty Print format
222    */
223   public static String prettyPrint(final Object object) {
224     try {
225       return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(object);
226     } catch (final JsonProcessingException e) {
227       return "{}";
228     }
229   }
230 
231   /**
232    * @param node
233    * @param field
234    *
235    * @return the String if the field exists, else null
236    */
237   public static String getString(final ObjectNode node, final String field) {
238     return getValue(node, field, (String) null);
239   }
240 
241   /**
242    * @param node
243    * @param field
244    *
245    * @return the String if the field exists, else null
246    */
247   public static String getString(final ObjectNode node, final Enum<?> field) {
248     return getValue(node, field.name(), (String) null);
249   }
250 
251   /**
252    * @param node
253    * @param field
254    * @param defValue
255    *
256    * @return the String if the field exists, else defValue
257    */
258   public static String getValue(final ObjectNode node, final String field,
259                                 final String defValue) {
260     final JsonNode elt = node.get(field);
261     if (elt != null) {
262       final String val = elt.asText();
263       if ("null".equals(val)) {
264         return defValue;
265       }
266       return val;
267     }
268     return defValue;
269   }
270 
271   /**
272    * @param node
273    * @param field
274    * @param defValue
275    *
276    * @return the Boolean if the field exists, else defValue
277    */
278   public static Boolean getValue(final ObjectNode node, final String field,
279                                  final boolean defValue) {
280     return node.path(field).asBoolean(defValue);
281   }
282 
283   /**
284    * @param node
285    * @param field
286    * @param defValue
287    *
288    * @return the Double if the field exists, else defValue
289    */
290   public static Double getValue(final ObjectNode node, final String field,
291                                 final double defValue) {
292     return node.path(field).asDouble(defValue);
293   }
294 
295   /**
296    * @param node
297    * @param field
298    * @param defValue
299    *
300    * @return the Long if the field exists, else defValue
301    */
302   public static Long getValue(final ObjectNode node, final String field,
303                               final long defValue) {
304     return node.path(field).asLong(defValue);
305   }
306 
307   /**
308    * @param node
309    * @param field
310    * @param defValue
311    *
312    * @return the Integer if the field exists, else defValue
313    */
314   public static Integer getValue(final ObjectNode node, final String field,
315                                  final int defValue) {
316     return node.path(field).asInt(defValue);
317   }
318 
319   /**
320    * @param node
321    * @param field
322    * @param defValue
323    *
324    * @return the byte array if the field exists, else defValue
325    */
326   public static byte[] getValue(final ObjectNode node, final String field,
327                                 final byte[] defValue) {
328     final JsonNode elt = node.get(field);
329     if (elt != null) {
330       try {
331         return elt.binaryValue();
332       } catch (final IOException e) {
333         return defValue;
334       }
335     }
336     return defValue;
337   }
338 
339   /**
340    * @param node
341    * @param field
342    * @param value
343    */
344   public static void setValue(final ObjectNode node, final String field,
345                               final boolean value) {
346     node.put(field, value);
347   }
348 
349   /**
350    * @param node
351    * @param field
352    * @param value
353    */
354   public static void setValue(final ObjectNode node, final String field,
355                               final double value) {
356     node.put(field, value);
357   }
358 
359   /**
360    * @param node
361    * @param field
362    * @param value
363    */
364   public static void setValue(final ObjectNode node, final String field,
365                               final int value) {
366     node.put(field, value);
367   }
368 
369   /**
370    * @param node
371    * @param field
372    * @param value
373    */
374   public static void setValue(final ObjectNode node, final String field,
375                               final long value) {
376     node.put(field, value);
377   }
378 
379   /**
380    * @param node
381    * @param field
382    * @param value
383    */
384   public static void setValue(final ObjectNode node, final String field,
385                               final String value) {
386     if (ParametersChecker.isEmpty(value)) {
387       return;
388     }
389     node.put(field, value);
390   }
391 
392   /**
393    * @param node
394    * @param field
395    * @param value
396    */
397   public static void setValue(final ObjectNode node, final String field,
398                               final byte[] value) {
399     if (value == null || value.length == 0) {
400       return;
401     }
402     node.put(field, value);
403   }
404 
405   /**
406    * @param node
407    * @param field
408    *
409    * @return True if all fields exist
410    */
411   public static boolean exist(final ObjectNode node, final String... field) {
412     for (final String string : field) {
413       if (!node.has(string)) {
414         return false;
415       }
416     }
417     return true;
418   }
419 
420   /**
421    * @param node
422    * @param field
423    * @param defValue
424    *
425    * @return the String if the field exists, else defValue
426    */
427   public static String getValue(final ObjectNode node, final Enum<?> field,
428                                 final String defValue) {
429     return getValue(node, field.name(), defValue);
430   }
431 
432   /**
433    * @param node
434    * @param field
435    * @param defValue
436    *
437    * @return the Boolean if the field exists, else defValue
438    */
439   public static Boolean getValue(final ObjectNode node, final Enum<?> field,
440                                  final boolean defValue) {
441     return node.path(field.name()).asBoolean(defValue);
442   }
443 
444   /**
445    * @param node
446    * @param field
447    * @param defValue
448    *
449    * @return the Double if the field exists, else defValue
450    */
451   public static Double getValue(final ObjectNode node, final Enum<?> field,
452                                 final double defValue) {
453     return node.path(field.name()).asDouble(defValue);
454   }
455 
456   /**
457    * @param node
458    * @param field
459    * @param defValue
460    *
461    * @return the Long if the field exists, else defValue
462    */
463   public static Long getValue(final ObjectNode node, final Enum<?> field,
464                               final long defValue) {
465     return node.path(field.name()).asLong(defValue);
466   }
467 
468   /**
469    * @param node
470    * @param field
471    * @param defValue
472    *
473    * @return the Integer if the field exists, else defValue
474    */
475   public static Integer getValue(final ObjectNode node, final Enum<?> field,
476                                  final int defValue) {
477     return node.path(field.name()).asInt(defValue);
478   }
479 
480   /**
481    * @param node
482    * @param field
483    * @param defValue
484    *
485    * @return the byte array if the field exists, else defValue
486    */
487   public static byte[] getValue(final ObjectNode node, final Enum<?> field,
488                                 final byte[] defValue) {
489     return getValue(node, field.name(), defValue);
490   }
491 
492   /**
493    * @param node
494    * @param field
495    * @param value
496    */
497   public static void setValue(final ObjectNode node, final Enum<?> field,
498                               final boolean value) {
499     node.put(field.name(), value);
500   }
501 
502   /**
503    * @param node
504    * @param field
505    * @param value
506    */
507   public static void setValue(final ObjectNode node, final Enum<?> field,
508                               final double value) {
509     node.put(field.name(), value);
510   }
511 
512   /**
513    * @param node
514    * @param field
515    * @param value
516    */
517   public static void setValue(final ObjectNode node, final Enum<?> field,
518                               final int value) {
519     node.put(field.name(), value);
520   }
521 
522   /**
523    * @param node
524    * @param field
525    * @param value
526    */
527   public static void setValue(final ObjectNode node, final Enum<?> field,
528                               final long value) {
529     node.put(field.name(), value);
530   }
531 
532   /**
533    * @param node
534    * @param field
535    * @param value
536    */
537   public static void setValue(final ObjectNode node, final Enum<?> field,
538                               final String value) {
539     if (ParametersChecker.isEmpty(value)) {
540       return;
541     }
542     node.put(field.name(), value);
543   }
544 
545   /**
546    * @param node
547    * @param field
548    * @param value
549    */
550   public static void setValue(final ObjectNode node, final Enum<?> field,
551                               final byte[] value) {
552     if (value == null || value.length == 0) {
553       return;
554     }
555     node.put(field.name(), value);
556   }
557 
558   /**
559    * @param node
560    * @param field
561    *
562    * @return True if all fields exist
563    */
564   public static boolean exist(final ObjectNode node, final Enum<?>... field) {
565     for (final Enum<?> enm : field) {
566       if (!node.has(enm.name())) {
567         return false;
568       }
569     }
570     return true;
571   }
572 
573   /**
574    * @param value
575    *
576    * @return the corresponding HashMap
577    */
578   public static Map<String, Object> getMapFromString(final String value) {
579     if (ParametersChecker.isNotEmpty(value)) {
580       Map<String, Object> info = null;
581       try {
582         info = mapper.readValue(value, typeReferenceMapStringObject);
583       } catch (final JsonParseException ignored) {
584         SysErrLogger.FAKE_LOGGER.ignoreLog(ignored);
585       } catch (final JsonMappingException ignored) {
586         SysErrLogger.FAKE_LOGGER.ignoreLog(ignored);
587       } catch (final IOException ignored) {
588         SysErrLogger.FAKE_LOGGER.ignoreLog(ignored);
589       }
590       if (info == null) {
591         info = new HashMap<String, Object>();
592       }
593       return info;
594     } else {
595       return new HashMap<String, Object>();
596     }
597   }
598 }