All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sta.cts.JSONScanner Maven / Gradle / Ivy

Go to download

Tool to convert CSV and XLS to XML, to transform XML and to convert XML to CSV, HTML, other text files, PDF etc., useful as command line tool and integrated in other projects.

There is a newer version: 3.119
Show newest version

package com.sta.cts;

import java.io.IOException;
import java.io.StringReader;
import java.util.Date;
import java.util.Hashtable;

import com.sta.mlogger.MLogger;

/**
 * 

Name: JSONScanner

*

Description: . *

*

Comment: ... *

*

Copyright: Copyright (c) 2018, 2019

*

Company: >StA-Soft<

* @author StA * @version 1.0 */ public class JSONScanner extends Scanner { // private static final String NULL_MAGIC = "___NULL_MAGIC___"; /** * Im JSON-Scanner verwendete Symbole. */ public enum JSONSym { /** * Array-Anfang ("["). */ ARRAY_BEGIN, /** * Array-Ende ("]"). */ ARRAY_END, /** * Object-Anfang ("{"). */ OBJECT_BEGIN, /** * Object-Ende ("}"). */ OBJECT_END, /** * Doppelpunkt (":"). */ COLON, /** * Komma (","). */ COMMA, /** * Null ("null"). */ NULL } /** * Operations-Level f?r JSON-Bl?tter. */ protected int myLevel = 0; /** * Aktuell zu verwendende JSON-Blatt-Hash-Tabelle. */ protected LeafHashtable myLHT = null; //=========================================================================== /** * Standard-Constructor. */ public JSONScanner() { } //=========================================================================== /** * Initialisierung mittels einer Hash-Tabelle. Schl?ssel ist der Name der * Einstellung, Wert ist der Wert der Einstellung. * @param pHT die Hash-Tabelle mit Einstellungen und Werten (beides Strings) */ @Override public void initH(Hashtable pHT) { // preOverread(); // siehe: init(is, enc) } //--------------------------------------------------------------------------- /** * ?berlie?t Spaces incl. #$09, #$0d, #$0a. Bei anderen Zeichen erfolgt ein * Abbruch. Das entscheidende Zeichen wird gelesen und zur?ckgeliefert. * @return letztes und entscheidendes Zeichen * @throws IOException falls ein Lesefehler auftritt */ protected char overreadSpaces() throws IOException { char ch; do { ch = getChar(); } while ((ch == ' ') || (ch == 0x09) || (ch == 0x0d) || (ch == 0x0a)); return ch; } /** * Zeichenkette parsen. Trennzeichen am Anfang muss bereits gelesen sein. * Abschlie?endes Trennzeichen wird ?berlesen. * @return Text f?r Zeichenkette (Inhalt zwischen Trennzeichen) * @throws IOException im Fehlerfall */ private String scanString() throws IOException { StringBuilder sb = new StringBuilder(); boolean ex = false; while (!ex) { char ch = getChar(); if (ch == 0x00) { MLogger.wrn("Missing end of String."); ex = true; } else if (ch == '\"') { // ungetChar(ch); ex = true; } else if (ch == '\\') { char ch1 = getChar(); if (ch1 == '\\') { sb.append(ch1); } else if (ch1 == '\"') { sb.append(ch1); } else if (ch1 == '/') { sb.append(ch1); } else if (ch1 == 'b') { sb.append('\b'); } else if (ch1 == 'f') { sb.append('\f'); } else if (ch1 == 'n') { sb.append('\n'); } else if (ch1 == 'r') { sb.append('\r'); } else if (ch1 == 't') { sb.append('\t'); } else if (ch1 == 'u') { StringBuilder sb1 = new StringBuilder(); for (int i = 0; i < 4; i++) { ch1 = getChar(); if (((ch1 >= '0') && (ch1 <= '9')) || ((ch1 >= 'a') && (ch1 <= 'f')) || ((ch1 >= 'A') && (ch1 <= 'F'))) { sb1.append(ch1); } else { throw new IOException("Invalid \\u combination: " + sb.toString() + ch1); } } int ic = Integer.valueOf(sb1.toString(), 16); sb.append((char) ic); } else { MLogger.wrn("Invalid character in mask sequence: " + ch1); ungetChar(ch1); ex = true; } } else { sb.append(ch); } } return sb.toString(); } /** * Schl?sselwort scannen. * @return Schl?sselwort * @throws IOException im Fehlerfall */ private String scanKeyWord() throws IOException { StringBuilder sb = new StringBuilder(); boolean ex = false; while (!ex) { char ch = getChar(); if (ch == 0x00) { ex = true; } else if ((ch >= 'a') && (ch <= 'z')) { sb.append(ch); } else { ungetChar(ch); ex = true; } } return sb.toString(); } /** * Zahl (Integer/Long und/oder Float/Double) scannen. * @return Number * @throws IOException im Fehlerfall */ private Number scanNumber() throws IOException { StringBuilder sb = new StringBuilder(); boolean isIntLong = true; boolean ex = false; while (!ex) { char ch = getChar(); if (ch == 0x00) { ex = true; } else if ((ch >= '0') && (ch <= '9')) { sb.append(ch); } else if ((ch == '+') || (ch == '-')) { sb.append(ch); } else if ((ch == '.') || (ch == 'E')) { sb.append(ch); isIntLong = false; } else { ungetChar(ch); ex = true; } } String s = sb.toString(); if (s.length() > 0) { if (isIntLong) { Long v = UniTypeConv.convString2Long(s); return ((v <= Integer.MAX_VALUE) && (v >= Integer.MIN_VALUE)) ? v.intValue() : v; } else { return UniTypeConv.convString2Double(s); } } return null; } /** * Holen eines neuen Tokens. * * Abstrakte Methode, mu? ?berschrieben werden. * * Ein Token ist ein Object. * * Ein Fehler (z. B. Dateiende) wird durch das Ergebnis "null" gekennzeichnet. * @return gibt ein Token oder null zur?ck */ @Override public Object getNewToken() { Object token = null; try { boolean ex = false; while (!ex) { char ch = overreadSpaces(); if (ch == 0x00) { ex = true; } else if (ch == '[') { token = JSONSym.ARRAY_BEGIN; ex = true; } else if (ch == ']') { token = JSONSym.ARRAY_END; ex = true; } else if (ch == '{') { token = JSONSym.OBJECT_BEGIN; ex = true; } else if (ch == '}') { token = JSONSym.OBJECT_END; ex = true; } else if (ch == ':') { token = JSONSym.COLON; ex = true; } else if (ch == ',') { token = JSONSym.COMMA; ex = true; } else if (ch == '\"') { token = scanString(); ex = true; } else if ((ch >= '0') && (ch <= '9')) { ungetChar(ch); token = scanNumber(); ex = true; } else if ((ch >= 'a') && (ch <= 'z')) { ungetChar(ch); String s = scanKeyWord(); if ("true".equals(s)) { return true; } else if ("false".equals(s)) { return false; } else if ("null".equals(s)) { return JSONSym.NULL; } else { MLogger.wrn("Invalid key word: " + s); return s; } } else { MLogger.wrn("Unknown character: " + ch); } } } catch (IOException e) { } return token; } /** * Pr?fen, ob ein bestimmtes Symbol folgt, und falls ja: ?berlesen. * @param sym Symbol * @return true: ja, Symbol gefunden, Symbol wurde ?berlesen, false: nein, anderes Symbol, Symbol wurde nicht ?berlesen */ public boolean check(JSONSym sym) { Object token = getToken(); if (token != sym) { ungetToken(token); return false; } return true; } /** * Es wird gepr?ft, ob ein Blatt mit dem angegebenen Namen folgt. Falls ja, werden Name, ":" und Wert gelesen, ein optional * folgendes "," ?berlesen und der Wert zur?ckgegeben. Falls nein, wird der Name zur?ckgelegt und null zur?ckgeliefert. * @param pName Name/Schl?ssel des Blatts * @return Wert des Blatts, falls vorhanden, sonst null * @throws Exception im Fehlerfall */ public Object getLeaf(String pName) throws Exception { Object token = getToken(); if ((token instanceof String) && (token.equals(pName))) { token = getToken(); if (token == JSONSym.COLON) { token = getToken(); if (token == null) { return null; } else if (token instanceof String) { check(JSONSym.COMMA); return token; } else if (token instanceof Number) { check(JSONSym.COMMA); return token; } else if (token instanceof Boolean) { check(JSONSym.COMMA); return token; } else if (token == JSONSym.NULL) { check(JSONSym.COMMA); return null; } else { MLogger.wrn("Invalid value: " + token); } } else { ungetToken(token); throw new Exception("Missing \":\", found: " + token); } } else { ungetToken(token); } return null; } /** * String-JSON-Blatt lesen. * @param pName der Name des JSON-Blatt-Tags * @return Inhalt als String * @throws Exception siehe getLeaf */ public String getLeafString(String pName) throws Exception { Object obj = getLeaf(pName); if (obj == null) { return null; } if (obj instanceof String) { return (String) obj; } throw new Exception("Invalid leaf type. Expected: String, found: " + obj); } /** * Integer-JSON-Blatt lesen. * @param pName der Name des JSON-Blatt-Tags * @return Inhalt als Integer * @throws Exception siehe getLeaf */ public Integer getLeafInt(String pName) throws Exception { Object obj = getLeaf(pName); if (obj == null) { return null; } if (obj instanceof Integer) { return (Integer) obj; } if (obj instanceof Long) { return ((Long) obj).intValue(); } throw new Exception("Invalid leaf type. Expected: Integer, found: " + obj); } /** * Long-JSON-Blatt lesen. * @param pName der Name des JSON-Blatt-Tags * @return Inhalt als Long * @throws Exception siehe getLeaf */ public Long getLeafLong(String pName) throws Exception { Object obj = getLeaf(pName); if (obj == null) { return null; } if (obj instanceof Long) { return (Long) obj; } if (obj instanceof Integer) { return ((Integer) obj).longValue(); } throw new Exception("Invalid leaf type. Expected: Long, found: " + obj); } /** * Float-JSON-Blatt lesen. * @param pName der Name des JSON-Blatt-Tags * @return Inhalt als Float * @throws Exception siehe getLeaf */ public Float getLeafFloat(String pName) throws Exception { Object obj = getLeaf(pName); if (obj == null) { return null; } if (obj instanceof Float) { return (Float) obj; } if (obj instanceof Double) { return ((Double) obj).floatValue(); } if (obj instanceof Integer) { return ((Integer) obj).floatValue(); } if (obj instanceof Long) { return ((Long) obj).floatValue(); } throw new Exception("Invalid leaf type. Expected: Float, found: " + obj); } /** * Double-JSON-Blatt lesen. * @param pName der Name des JSON-Blatt-Tags * @return Inhalt als Double * @throws Exception siehe getLeaf */ public Double getLeafDouble(String pName) throws Exception { Object obj = getLeaf(pName); if (obj == null) { return null; } if (obj instanceof Double) { return (Double) obj; } if (obj instanceof Float) { return ((Float) obj).doubleValue(); } if (obj instanceof Integer) { return ((Integer) obj).doubleValue(); } if (obj instanceof Long) { return ((Long) obj).doubleValue(); } throw new Exception("Invalid leaf type. Expected: Double, found: " + obj); } /** * Date-JSON-Blatt lesen. * @param pName der Name des JSON-Blatt-Tags * @param pMask optionale Maske * @return Inhalt als Date (nur Datum) * @throws Exception siehe getLeaf */ public Date getLeafDate(String pName, String pMask) throws Exception { Object obj = getLeaf(pName); if (obj == null) { return null; } if (obj instanceof String) { return UniTypeConv.convString2Date((String) obj, pMask); } throw new Exception("Invalid leaf type. Expected: String for Date, found: " + obj); } /** * Date-JSON-Blatt lesen. * @param pName der Name des JSON-Blatt-Tags * @return Inhalt als Date (nur Datum) * @throws Exception siehe getLeaf */ public Date getLeafDate(String pName) throws Exception { return getLeafDate(pName, null); } /** * Time-JSON-Blatt lesen. * @param pName der Name des JSON-Blatt-Tags * @param pMask optionale Maske * @return Inhalt als Date (nur Zeitangabe) * @throws Exception siehe getLeaf */ public Date getLeafTime(String pName, String pMask) throws Exception { Object obj = getLeaf(pName); if (obj == null) { return null; } if (obj instanceof String) { return UniTypeConv.convString2Time((String) obj, pMask); } throw new Exception("Invalid leaf type. Expected: String for Time, found: " + obj); } /** * Time-JSON-Blatt lesen. * @param pName der Name des JSON-Blatt-Tags * @return Inhalt als Date (nur Zeitangabe) * @throws Exception siehe getLeaf */ public Date getLeafTime(String pName) throws Exception { return getLeafTime(pName, null); } /** * DateTime-JSON-Blatt lesen. * @param pName der Name des JSON-Blatt-Tags * @param pMask optionale Maske * @return Inhalt als Date (Datum und Zeitangabe) * @throws Exception siehe getLeaf */ public Date getLeafDateTime(String pName, String pMask) throws Exception { Object obj = getLeaf(pName); if (obj == null) { return null; } if (obj instanceof String) { return UniTypeConv.convString2DateTime((String) obj, pMask); } throw new Exception("Invalid leaf type. Expected: String for DateTime, found: " + obj); } /** * DateTime-JSON-Blatt lesen. * @param pName der Name des JSON-Blatt-Tags * @return Inhalt als Date (Datum und Zeitangabe) * @throws Exception siehe getLeaf */ public Date getLeafDateTime(String pName) throws Exception { return getLeafDateTime(pName, null); } /** * Boolean-JSON-Blatt lesen. * @param pName der Name des JSON-Blatt-Tags * @return Inhalt als Boolean * @throws Exception siehe getLeaf */ public Boolean getLeafBool(String pName) throws Exception { Object obj = getLeaf(pName); if (obj == null) { return null; } if (obj instanceof Boolean) { return (Boolean) obj; } throw new Exception("Invalid leaf type. Expected: Boolean, found: " + obj); } /** * myLevel erh?hen. */ public void incLevel() { myLevel++; } /** * myLevel verringern. */ public void decLevel() { myLevel--; } /** * Ermittlung der LeafHashtable, um z. B. zu pr?fen, ob diese nach Laden * eines TO's auch wirklich leer ist. * @return die LHT */ public LeafHashtable getLHT() { return myLHT; } /** * Spezielle Hashtabelle aus JSON-Bl?ttern erzeugen. * In der Hashtabelle liegen unter den JSON-Blatt(-Tag)-Namen (String) als * Schl?ssel der Wert des jeweiligen Blatts (ebenfalls als String). * Object-Anfang muss gelesen worden sein. Object-Ende wird nicht ?berlesen. * @return diese Hashtabelle * @throws Exception falls ein Lesefehler auftritt, ebenso im Falle von JSON-Struktur-Fehlern */ public LeafHashtable getLeafs() throws Exception { if (myLevel != 0) { return myLHT; } myLHT = new LeafHashtable(); boolean cont = false; do { Object token = getToken(); if (!(token instanceof String)) { ungetToken(token); // Falls nach einem Blatt bereits ein "," gelesen wurde, dann MUSS ein neues Blatt (und somit ein String) kommen! // if (cont) // { // throw new Exception("JSON-Error 0 (missing name/key for leaf, found: " + (token != null ? token.toString() : "(null)") + ")"); // } break; } String name = (String) token; token = getToken(); if (token != JSONSym.COLON) { throw new Exception("JSON-Error 1 (missing colon ':' in leaf: " + name + ", found: " + (token != null ? token.toString() : "(null)") + ")"); } token = getToken(); String s = ""; if (token instanceof String) { s = (String) token; } else if (token instanceof Integer) { s = UniTypeConv.convInt2String((Integer) token); } else if (token instanceof Long) { s = UniTypeConv.convLong2String((Long) token); } else if (token instanceof Float) { s = UniTypeConv.convFloat2String((Float) token); } else if (token instanceof Double) { s = UniTypeConv.convDouble2String((Double) token); } else if (token instanceof Boolean) { s = UniTypeConv.convBool2String((Boolean) token); } else { throw new Exception("JSON-Error 2 (invalid value type in leaf: " + name + ", found: " + (token != null ? token.toString() : "(null)") + ")"); } myLHT.put(name, s); cont = check(JSONSym.COMMA); } while (cont); return myLHT; } /** * Pr?fen, ob die Leaf-Hash-Tabelle (LHT) leer ist, falls nicht: Meldungen (als Warnungen) ausgeben. * @param lht die LHT * @param text Text f?r die Meldung. */ public static void checkLHT(LeafHashtable lht, String text) { if ((lht != null) && !lht.isEmpty()) { lht.forEach((key, value) -> MLogger.wrn("LHT (" + text + ") not empty: " + "\"" + key + "\" : " + value)); /* Enumeration e = lht.keys(); while (e.hasMoreElements()) { String key = (String) e.nextElement(); String val = (String) lht.get(key); MLogger.wrn("LHT (" + text + ") not empty: " + "\"" + key + "\" : " + val); } */ MLogger.wrn("Please check JSON-Source-File!"); } } /** * Pr?fen, ob die Leaf-Hash-Tabelle (LHT) leer ist, falls nicht: Meldungen (als Warnungen) ausgeben, * Darf nur nach getLeafs() verwendet werden, bezieht sich auf das letzte getLeafs(). * @param text Text f?r die Meldung. */ public void checkLHT(String text) { checkLHT(myLHT, text); } //=========================================================================== /** * Main-Methode. * @param args Kommandozeilenargumente */ public static void main(String... args) { try { JSONScanner js = new JSONScanner(); String s = "\"Strg\" : \"Hallo!\", \"Strg1\" : \"Hallo1!\""; js.init(new StringReader(s)); Object obj = js.getLeaf("Strg"); MLogger.deb(() -> "obj: " + obj); Object obj1 = js.getLeaf("Strg1"); MLogger.deb(() -> "obj1: " + obj1); js.close(); s = "\"Strg\" : \"Hallo!\", \"Strg1\" : \"Hallo1!\", \"Int\" : \"0\", \"Int1\" : \"1\""; js.init(new StringReader(s)); LeafHashtable lht = js.getLeafs(); MLogger.deb(() -> "result: " + lht.toString()); MLogger.deb(() -> "lht-int-as-int: " + lht.getLeafInt("Int")); MLogger.deb(() -> "lht-int-as-string: " + lht.getLeafString("Int1")); js.checkLHT("test"); js.close(); } catch (Exception ex) { MLogger.err("", ex); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy