com.viaoa.util.OAJsonReader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of oa Show documentation
Show all versions of oa Show documentation
Object Automation library
The newest version!
/* Copyright 1999-2015 Vince Via [email protected]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package com.viaoa.util;
import java.util.ArrayList;
import com.viaoa.object.OAObject;
/**
OAJsonReader that converts to XML, and then uses OAXMLReader to convert to OAObjects and Hubs.
@see OAJsonWriter
@author vvia
@since 20120518
*/
public class OAJsonReader {
private String jsonText;
private int len;
private int pos;
private StringBuilder sb;
private JsonToken token, lastToken;
private Class rootClass;
/**
* Parses the JSON text and returns the root object(s).
* @param rootClass class for the root object. If it is a Hub, then it needs to be the OAObjectClass of the Hub.
*/
public Object[] parse(String json, Class rootClass) {
try {
String xml = convertToXML(json, rootClass);
OAXMLReader xmlReader = new OAXMLReader() {
@Override
public Object convertToObject(String propertyName, String value, Class propertyClass) {
if ("null".equals(value)) {
return null;
}
if (OADate.class.equals(propertyClass)) return new OADate(value, "yyyy-MM-dd");
if (OATime.class.equals(propertyClass)) return new OATime(value, "HH:mm:ss");
if (OADateTime.class.equals(propertyClass)) return new OADate(value, "yyyy-MM-dd'T'HH:mm:ss");
return super.convertToObject(propertyName, value, propertyClass);
}
@Override
protected String resolveClassName(String className) {
return OAJsonReader.this.getClassName(className);
}
@Override
public Object getValue(OAObject obj, String name, Object value) {
return OAJsonReader.this.getValue(obj, name, value);
}
@Override
protected String getPropertyName(OAObject obj, String propName) {
return OAJsonReader.this.getPropertyName(obj, propName);
}
@Override
public void endObject(OAObject obj, boolean hasParent) {
OAJsonReader.this.endObject(obj, hasParent);
}
};
Object[] objs = xmlReader.readXML(xml);
return objs;
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
// get the classname to use for a property
protected String getClassName(String className) {
//System.out.println("getClassName className="+className);//qqqqqqqqq
// className = "com.viaoa.object.OAObject";
return className;
}
// get the propertyName to use
protected String getPropertyName(OAObject obj, String propName) {
//System.out.println("getPropertyName obj="+obj+", propName="+propName);//qqqqqqqqq
//propName = null;
return propName;
}
// get the value to use when setting a property
protected Object getValue(OAObject obj, String name, Object value) {
//System.out.println("getValue obj="+obj+", propName="+name+", value="+value);//qqqqqqqqq
return value;
}
protected void endObject(OAObject obj, boolean hasParent) {
}
// 20141222 rewrote
public String convertToXML(String jsonText, Class rootClass) {
this.jsonText = jsonText;
this.rootClass = rootClass;
pos = 0;
len = jsonText.length();
sb = new StringBuilder(len*3);
sb.append("\n");
sb.append("\n");
//sb.append("\n");
for (int i=0; ;i++) {
parseRootObject();
if (token.type == TokenType.eof) break;
}
//sb.append(" \n");
sb.append(" \n");
return new String(sb);
}
protected void parseRootObject() {
for (int i=0; ;i++) {
nextToken();
if (token.type == TokenType.eof) break;
if (token.type == TokenType.string) {
String s = token.value;
nextToken();
parseObject(s);
}
else {
parseObject(rootClass.getName());
}
}
}
protected void parseObject(String name) {
name = OAString.trim(name);
if (token.type == TokenType.leftSquareBracket) {
parseObjects(name);
}
else if (token.type == TokenType.leftBracket) {
sb.append("<"+name+">\n");
parseProperties();
sb.append(""+name+">\n");
}
}
protected void parseObjects(String name) {
for (;;) {
nextToken();
if (token.type == TokenType.rightSquareBracket) break;
if (token.type == TokenType.eof) break;
parseObject(name);
}
}
protected void parseProperties() {
for (;;) {
nextToken();
if (token.type == TokenType.rightBracket) break;
if (token.type == TokenType.eof) break;
String pname = OAString.trim(token.value);
nextToken(); // colon
nextToken(); // propValue, [, or {
if (token.type == TokenType.leftSquareBracket || token.type == TokenType.leftBracket) {
parseObject(pname);
}
else {
sb.append("<"+pname+">");
sb.append(token.value);
sb.append(""+pname+">\n");
}
}
}
//qqqqqqqqqqqqqqqq end
/**
* Convert to OAXML so that OAXMLReader can be used to load the Hubs and OAObjects
* @param rootClass class for the root object. If it is a Hub, then it needs to be the OAObjectClass of the Hub.
*/
// NOT USED qqqqqqqqq
public String convertToXML__OLD__(String jsonText, Class rootClass) {
this.jsonText = jsonText;
this.rootClass = rootClass;
pos = 0;
len = jsonText.length();
sb = new StringBuilder(len*3);
sb.append("\n");
sb.append("\n");
convert(false);
sb.append(" \n");
return new String(sb);
}
/* A "INSERTCLASS" will be inserted as a placeholder for the class name. OAXMLReader will then
find the correct value when it is converting to objects.
*/
// NOT USED qqqqqqqqq
protected void convert(boolean bNeedsTag) {
boolean bFirstEver = (token == null && lastToken == null);
boolean bFirstIsHub = false;
for (;;) {
nextToken();
if (bFirstEver && lastToken == null) {
if (token.type == TokenType.leftSquareBracket) {
sb.append("\n");
bFirstIsHub = true;
}
else sb.append("<"+rootClass.getName()+">\n");
}
if (token.type == TokenType.eof) break;
if (token.type == TokenType.comma) continue;
if (token.type == TokenType.rightBracket) break;
if (token.type == TokenType.rightSquareBracket) break;
String name = null;
if (token.type == TokenType.string) {
//qqqq name = getName(token.value);
sb.append("<" + name + ">");
nextToken();
if (token.type == TokenType.colon) nextToken();
}
if (token.type == TokenType.leftBracket) {
if (bNeedsTag) sb.append("\n");
convert(true);
if (bNeedsTag) sb.append(" \n");
}
else if (token.type == TokenType.leftSquareBracket) {
if (bNeedsTag) sb.append("\n");
convert(true); // convert all of the objects in the collection
if (bNeedsTag) sb.append(" \n");
}
else {
// see if is needed qqqqqqqqqqqqq
sb.append(token.value);
}
if (name != null) sb.append("" + name + ">\n");
}
if (bFirstEver) {
if (bFirstIsHub) {
sb.append(" \n");
}
else sb.append(""+rootClass.getName()+">\n");
}
}
protected void nextToken() {
lastToken = token;
token = getNext();
}
static class JsonToken {
TokenType type;
String value;
}
enum TokenType {
string,
number,
colon,
comma,
leftBracket,
rightBracket,
leftSquareBracket,
rightSquareBracket,
eof
}
public JsonToken getNext() {
JsonToken token = new JsonToken();
char charWaitFor = 0;
char ch=0, chLast;
boolean bReturn = false;
String sError = null;
StringBuilder sb = new StringBuilder(64);
boolean bComma = false;
for ( ; !bReturn && pos= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_') {
token.type = TokenType.string;
}
else {
sError = "Illegal token '"+ch+"'";
bReturn = true;
}
}
else if (token.type == TokenType.number) {
if (!Character.isDigit(ch)) {
token.type = TokenType.string;
}
}
else if (ch == '{' || ch == '}' || ch == '[' || ch == ']') {
break;
}
if (bComma) {
sb.append(',');
bComma = false;
}
sb.append(ch);
}
if (sError != null) {
throw new RuntimeException(sError + " at position "+pos+" in json string=" + jsonText);
}
token.value = new String(sb);
if (token.type == null) token.type = TokenType.eof;
return token;
}
}