From 34b1b2be14af878be2c093806c5e74fcd6b5f372 Mon Sep 17 00:00:00 2001 From: Ralph Niemitz Date: Sun, 30 Jul 2017 15:39:54 +0200 Subject: [PATCH] 2017-07-30 Signed-off-by: Ralph Niemitz --- src/de/ralleytn/simple/json/JSONArray.java | 10 +- ...Factory.java => JSONContainerFactory.java} | 9 +- .../simple/json/JSONContentHandler.java | 309 ++++++++++ src/de/ralleytn/simple/json/JSONObject.java | 10 +- ...Exception.java => JSONParseException.java} | 14 +- .../simple/json/{parser => }/JSONParser.java | 118 ++-- .../ralleytn/simple/json/JSONSerializer.java | 527 +++++++++++++++--- ...java => JSONTypeSerializationHandler.java} | 113 +--- src/de/ralleytn/simple/json/JSONValue.java | 6 +- .../simple/json/{parser => }/Yylex.java | 187 +------ .../simple/json/{parser => }/Yytoken.java | 4 +- src/test/JSONFormatterTest.java | 21 - src/test/JSONObjectTest.java | 16 - src/test/JSONParserTest.java | 19 - src/test/JSONSerializerTest.java | 28 - src/test/Person.java | 97 ---- src/test/Product.java | 25 - 17 files changed, 888 insertions(+), 625 deletions(-) rename src/de/ralleytn/simple/json/{parser/ContainerFactory.java => JSONContainerFactory.java} (98%) create mode 100644 src/de/ralleytn/simple/json/JSONContentHandler.java rename src/de/ralleytn/simple/json/{parser/ParseException.java => JSONParseException.java} (97%) rename src/de/ralleytn/simple/json/{parser => }/JSONParser.java (88%) rename src/de/ralleytn/simple/json/{parser/ContentHandler.java => JSONTypeSerializationHandler.java} (79%) rename src/de/ralleytn/simple/json/{parser => }/Yylex.java (72%) rename src/de/ralleytn/simple/json/{parser => }/Yytoken.java (99%) delete mode 100644 src/test/JSONFormatterTest.java delete mode 100644 src/test/JSONObjectTest.java delete mode 100644 src/test/JSONParserTest.java delete mode 100644 src/test/JSONSerializerTest.java delete mode 100644 src/test/Person.java delete mode 100644 src/test/Product.java diff --git a/src/de/ralleytn/simple/json/JSONArray.java b/src/de/ralleytn/simple/json/JSONArray.java index 8ba866b..9de1cc3 100644 --- a/src/de/ralleytn/simple/json/JSONArray.java +++ b/src/de/ralleytn/simple/json/JSONArray.java @@ -215,8 +215,6 @@ import java.util.Date; import java.util.Iterator; -import de.ralleytn.simple.json.parser.JSONParser; - /** * Represents a JSON array. * @author FangYidong(fangyidong@yahoo.com.cn) @@ -381,10 +379,10 @@ public JSONArray(Object array) { /** * Constructs a {@linkplain JSONArray} from JSON data. * @param json the JSON data - * @throws de.ralleytn.simple.json.parser.ParseException if the JSON data is invalid + * @throws JSONParseException if the JSON data is invalid * @since 1.0.0 */ - public JSONArray(String json) throws de.ralleytn.simple.json.parser.ParseException { + public JSONArray(String json) throws JSONParseException { super((JSONArray)new JSONParser().parse(json)); } @@ -392,11 +390,11 @@ public JSONArray(String json) throws de.ralleytn.simple.json.parser.ParseExcepti /** * Constructs a {@linkplain JSONArray} from JSON data read from a {@linkplain Reader}. * @param jsonReader the {@linkplain Reader} with the JSON data - * @throws de.ralleytn.simple.json.parser.ParseException if the JSON data is invalid + * @throws JSONParseException if the JSON data is invalid * @throws IOException if an I/O error occurred * @since 1.0.0 */ - public JSONArray(Reader jsonReader) throws de.ralleytn.simple.json.parser.ParseException, IOException { + public JSONArray(Reader jsonReader) throws JSONParseException, IOException { super((JSONArray)new JSONParser().parse(jsonReader)); } diff --git a/src/de/ralleytn/simple/json/parser/ContainerFactory.java b/src/de/ralleytn/simple/json/JSONContainerFactory.java similarity index 98% rename from src/de/ralleytn/simple/json/parser/ContainerFactory.java rename to src/de/ralleytn/simple/json/JSONContainerFactory.java index 076c5b7..96b8b21 100644 --- a/src/de/ralleytn/simple/json/parser/ContainerFactory.java +++ b/src/de/ralleytn/simple/json/JSONContainerFactory.java @@ -201,23 +201,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package de.ralleytn.simple.json.parser; +package de.ralleytn.simple.json; import java.util.List; import java.util.Map; -import de.ralleytn.simple.json.JSONArray; -import de.ralleytn.simple.json.JSONObject; - /** * Container factory which creates containers for {@linkplain JSONObject} and {@linkplain JSONArray}. - * @see de.ralleytn.simple.json.parser.JSONParser#parse(java.io.Reader, ContainerFactory) + * @see de.ralleytn.simple.json.JSONParser#parse(java.io.Reader, ContainerFactory) * @author FangYidong(fangyidong@yahoo.com.cn) * @author Ralph Niemitz/RalleYTN(ralph.niemitz@gmx.de) * @version 1.0.0 * @since 1.0.0 */ -public interface ContainerFactory { +public interface JSONContainerFactory { /** * @return A {@linkplain Map} instance to store the data for a JSON object, or {@code null} if you want to use {@linkplain JSONObject} instead.. diff --git a/src/de/ralleytn/simple/json/JSONContentHandler.java b/src/de/ralleytn/simple/json/JSONContentHandler.java new file mode 100644 index 0000000..e3a075c --- /dev/null +++ b/src/de/ralleytn/simple/json/JSONContentHandler.java @@ -0,0 +1,309 @@ +/* + * Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + * + * 1. Definitions. + * + * "License" shall mean the terms and conditions for use, reproduction, + * and distribution as defined by Sections 1 through 9 of this document. + * + * "Licensor" shall mean the copyright owner or entity authorized by + * the copyright owner that is granting the License. + * + * "Legal Entity" shall mean the union of the acting entity and all + * other entities that control, are controlled by, or are under common + * control with that entity. For the purposes of this definition, + * "control" means (i) the power, direct or indirect, to cause the + * direction or management of such entity, whether by contract or + * otherwise, or (ii) ownership of fifty percent (50%) or more of the + * outstanding shares, or (iii) beneficial ownership of such entity. + * + * "You" (or "Your") shall mean an individual or Legal Entity + * exercising permissions granted by this License. + * + * "Source" form shall mean the preferred form for making modifications, + * including but not limited to software source code, documentation + * source, and configuration files. + * + * "Object" form shall mean any form resulting from mechanical + * transformation or translation of a Source form, including but + * not limited to compiled object code, generated documentation, + * and conversions to other media types. + * + * "Work" shall mean the work of authorship, whether in Source or + * Object form, made available under the License, as indicated by a + * copyright notice that is included in or attached to the work + * (an example is provided in the Appendix below). + * + * "Derivative Works" shall mean any work, whether in Source or Object + * form, that is based on (or derived from) the Work and for which the + * editorial revisions, annotations, elaborations, or other modifications + * represent, as a whole, an original work of authorship. For the purposes + * of this License, Derivative Works shall not include works that remain + * separable from, or merely link (or bind by name) to the interfaces of, + * the Work and Derivative Works thereof. + * + * "Contribution" shall mean any work of authorship, including + * the original version of the Work and any modifications or additions + * to that Work or Derivative Works thereof, that is intentionally + * submitted to Licensor for inclusion in the Work by the copyright owner + * or by an individual or Legal Entity authorized to submit on behalf of + * the copyright owner. For the purposes of this definition, "submitted" + * means any form of electronic, verbal, or written communication sent + * to the Licensor or its representatives, including but not limited to + * communication on electronic mailing lists, source code control systems, + * and issue tracking systems that are managed by, or on behalf of, the + * Licensor for the purpose of discussing and improving the Work, but + * excluding communication that is conspicuously marked or otherwise + * designated in writing by the copyright owner as "Not a Contribution." + * + * "Contributor" shall mean Licensor and any individual or Legal Entity + * on behalf of whom a Contribution has been received by Licensor and + * subsequently incorporated within the Work. + * + * 2. Grant of Copyright License. Subject to the terms and conditions of + * this License, each Contributor hereby grants to You a perpetual, + * worldwide, non-exclusive, no-charge, royalty-free, irrevocable + * copyright license to reproduce, prepare Derivative Works of, + * publicly display, publicly perform, sublicense, and distribute the + * Work and such Derivative Works in Source or Object form. + * + * 3. Grant of Patent License. Subject to the terms and conditions of + * this License, each Contributor hereby grants to You a perpetual, + * worldwide, non-exclusive, no-charge, royalty-free, irrevocable + * (except as stated in this section) patent license to make, have made, + * use, offer to sell, sell, import, and otherwise transfer the Work, + * where such license applies only to those patent claims licensable + * by such Contributor that are necessarily infringed by their + * Contribution(s) alone or by combination of their Contribution(s) + * with the Work to which such Contribution(s) was submitted. If You + * institute patent litigation against any entity (including a + * cross-claim or counterclaim in a lawsuit) alleging that the Work + * or a Contribution incorporated within the Work constitutes direct + * or contributory patent infringement, then any patent licenses + * granted to You under this License for that Work shall terminate + * as of the date such litigation is filed. + * + * 4. Redistribution. You may reproduce and distribute copies of the + * Work or Derivative Works thereof in any medium, with or without + * modifications, and in Source or Object form, provided that You + * meet the following conditions: + * + * (a) You must give any other recipients of the Work or + * Derivative Works a copy of this License; and + * + * (b) You must cause any modified files to carry prominent notices + * stating that You changed the files; and + * + * (c) You must retain, in the Source form of any Derivative Works + * that You distribute, all copyright, patent, trademark, and + * attribution notices from the Source form of the Work, + * excluding those notices that do not pertain to any part of + * the Derivative Works; and + * + * (d) If the Work includes a "NOTICE" text file as part of its + * distribution, then any Derivative Works that You distribute must + * include a readable copy of the attribution notices contained + * within such NOTICE file, excluding those notices that do not + * pertain to any part of the Derivative Works, in at least one + * of the following places: within a NOTICE text file distributed + * as part of the Derivative Works; within the Source form or + * documentation, if provided along with the Derivative Works; or, + * within a display generated by the Derivative Works, if and + * wherever such third-party notices normally appear. The contents + * of the NOTICE file are for informational purposes only and + * do not modify the License. You may add Your own attribution + * notices within Derivative Works that You distribute, alongside + * or as an addendum to the NOTICE text from the Work, provided + * that such additional attribution notices cannot be construed + * as modifying the License. + * + * You may add Your own copyright statement to Your modifications and + * may provide additional or different license terms and conditions + * for use, reproduction, or distribution of Your modifications, or + * for any such Derivative Works as a whole, provided Your use, + * reproduction, and distribution of the Work otherwise complies with + * the conditions stated in this License. + * + * 5. Submission of Contributions. Unless You explicitly state otherwise, + * any Contribution intentionally submitted for inclusion in the Work + * by You to the Licensor shall be under the terms and conditions of + * this License, without any additional terms or conditions. + * Notwithstanding the above, nothing herein shall supersede or modify + * the terms of any separate license agreement you may have executed + * with Licensor regarding such Contributions. + * + * 6. Trademarks. This License does not grant permission to use the trade + * names, trademarks, service marks, or product names of the Licensor, + * except as required for reasonable and customary use in describing the + * origin of the Work and reproducing the content of the NOTICE file. + * + * 7. Disclaimer of Warranty. Unless required by applicable law or + * agreed to in writing, Licensor provides the Work (and each + * Contributor provides its Contributions) on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied, including, without limitation, any warranties or conditions + * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + * PARTICULAR PURPOSE. You are solely responsible for determining the + * appropriateness of using or redistributing the Work and assume any + * risks associated with Your exercise of permissions under this License. + * + * 8. Limitation of Liability. In no event and under no legal theory, + * whether in tort (including negligence), contract, or otherwise, + * unless required by applicable law (such as deliberate and grossly + * negligent acts) or agreed to in writing, shall any Contributor be + * liable to You for damages, including any direct, indirect, special, + * incidental, or consequential damages of any character arising as a + * result of this License or out of the use or inability to use the + * Work (including but not limited to damages for loss of goodwill, + * work stoppage, computer failure or malfunction, or any and all + * other commercial damages or losses), even if such Contributor + * has been advised of the possibility of such damages. + * + * 9. Accepting Warranty or Additional Liability. While redistributing + * the Work or Derivative Works thereof, You may choose to offer, + * and charge a fee for, acceptance of support, warranty, indemnity, + * or other liability obligations and/or rights consistent with this + * License. However, in accepting such obligations, You may act only + * on Your own behalf and on Your sole responsibility, not on behalf + * of any other Contributor, and only if You agree to indemnify, + * defend, and hold each Contributor harmless for any liability + * incurred by, or claims asserted against, such Contributor by reason + * of your accepting any such warranty or additional liability. + * + * END OF TERMS AND CONDITIONS + * + * APPENDIX: How to apply the Apache License to your work. + * + * To apply the Apache License to your work, attach the following + * boilerplate notice, with the fields enclosed by brackets "{}" + * replaced with your own identifying information. (Don't include + * the brackets!) The text should be enclosed in the appropriate + * comment syntax for the file format. We also recommend that a + * file or class name and description of purpose be included on the + * same "printed page" as the copyright notice for easier + * identification within third-party archives. + * + * Copyright {yyyy} {name of copyright owner} + * + * 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 de.ralleytn.simple.json; + +import java.io.IOException; + +/** + * A simplified and stoppable SAX-like content handler for stream processing of JSON text. + * @see org.xml.sax.ContentHandler + * @see de.ralleytn.simple.json.JSONParser#parse(java.io.Reader, JSONContentHandler, boolean) + * @author FangYidong(fangyidong@yahoo.com.cn) + * @version 1.0.0 + * @since 1.0.0 + */ +public interface JSONContentHandler { + /** + * Receives a notification when the JSON processing begins. + * The {@linkplain JSONParser} will invoke this method only once. + * @throws JSONParseException {@linkplain JSONParser} will stop and throw the same {@linkplain Exception} to the caller when receiving this {@linkplain Exception}. + * @throws IOException {@linkplain JSONParser} will stop and throw the same {@linkplain Exception} to the caller when receiving this {@linkplain Exception}. + * @since 1.0.0 + */ + public void startJSON() throws JSONParseException, IOException; + + /** + * Receives a notification when the JSON processing ends. + * @throws JSONParseException {@linkplain JSONParser} will stop and throw the same {@linkplain Exception} to the caller when receiving this {@linkplain Exception}. + * @throws IOException {@linkplain JSONParser} will stop and throw the same {@linkplain Exception} to the caller when receiving this {@linkplain Exception}. + * @since 1.0.0 + */ + public void endJSON() throws JSONParseException, IOException; + + /** + * Receives a notification when a JSON object begins. + * @return {@code false} if the {@linkplain JSONContentHandler} wants to stop parsing after return + * @throws JSONParseException {@linkplain JSONParser} will stop and throw the same {@linkplain Exception} to the caller when receiving this {@linkplain Exception}. + * @throws IOException {@linkplain JSONParser} will stop and throw the same {@linkplain Exception} to the caller when receiving this {@linkplain Exception}. + * @see #endJSON + * @since 1.0.0 + */ + public boolean startObject() throws JSONParseException, IOException; + + /** + * Receives a notification when a JSON object ends. + * @return {@code false} if the {@linkplain JSONContentHandler} wants to stop parsing after return + * @throws JSONParseException {@linkplain JSONParser} will stop and throw the same {@linkplain Exception} to the caller when receiving this {@linkplain Exception}. + * @throws IOException {@linkplain JSONParser} will stop and throw the same {@linkplain Exception} to the caller when receiving this {@linkplain Exception}. + * @see #startObject + * @since 1.0.0 + */ + public boolean endObject() throws JSONParseException, IOException; + + /** + * Receives a notification when a JSON object entry begins. + * @param key name of the object entry + * @return {@code false} if the {@linkplain JSONContentHandler} wants to stop parsing after return + * @throws JSONParseException {@linkplain JSONParser} will stop and throw the same {@linkplain Exception} to the caller when receiving this {@linkplain Exception}. + * @throws IOException {@linkplain JSONParser} will stop and throw the same {@linkplain Exception} to the caller when receiving this {@linkplain Exception}. + * @see #endObjectEntry + * @since 1.0.0 + */ + public boolean startObjectEntry(String key) throws JSONParseException, IOException; + + /** + * Receives a notification when a JSON entry ends. + * @return {@code false} if the {@linkplain JSONContentHandler} wants to stop parsing after return + * @throws JSONParseException {@linkplain JSONParser} will stop and throw the same {@linkplain Exception} to the caller when receiving this {@linkplain Exception}. + * @throws IOException {@linkplain JSONParser} will stop and throw the same {@linkplain Exception} to the caller when receiving this {@linkplain Exception}. + * @see #startObjectEntry + */ + public boolean endObjectEntry() throws JSONParseException, IOException; + + /** + * Receives a notification when a JSON array begins. + * @return {@code false} if the {@linkplain JSONContentHandler} wants to stop parsing after return + * @throws JSONParseException {@linkplain JSONParser} will stop and throw the same {@linkplain Exception} to the caller when receiving this {@linkplain Exception}. + * @throws IOException {@linkplain JSONParser} will stop and throw the same {@linkplain Exception} to the caller when receiving this {@linkplain Exception}. + * @see #endArray + * @since 1.0.0 + */ + public boolean startArray() throws JSONParseException, IOException; + + /** + * Receives a notification when a JSON array ends. + * @return {@code false} if the {@linkplain JSONContentHandler} wants to stop parsing after return + * @throws JSONParseException {@linkplain JSONParser} will stop and throw the same {@linkplain Exception} to the caller when receiving this {@linkplain Exception}. + * @throws IOException {@linkplain JSONParser} will stop and throw the same {@linkplain Exception} to the caller when receiving this {@linkplain Exception}. + * @see #startArray + * @since 1.0.0 + */ + public boolean endArray() throws JSONParseException, IOException; + + /** + * Receives a notification when a primitive JSON value is reached: + * + * @param value the primitive JSON value + * @return {@code false} if the {@linkplain JSONContentHandler} wants to stop parsing after return + * @throws JSONParseException {@linkplain JSONParser} will stop and throw the same {@linkplain Exception} to the caller when receiving this {@linkplain Exception}. + * @throws IOException {@linkplain JSONParser} will stop and throw the same {@linkplain Exception} to the caller when receiving this {@linkplain Exception}. + * @since 1.0.0 + */ + public boolean primitive(Object value) throws JSONParseException, IOException; +} diff --git a/src/de/ralleytn/simple/json/JSONObject.java b/src/de/ralleytn/simple/json/JSONObject.java index a7ed9cf..8309e0f 100644 --- a/src/de/ralleytn/simple/json/JSONObject.java +++ b/src/de/ralleytn/simple/json/JSONObject.java @@ -214,8 +214,6 @@ import java.util.LinkedHashMap; import java.util.Map; -import de.ralleytn.simple.json.parser.JSONParser; - /** * Represents a JSON object. * @author FangYidong(fangyidong@yahoo.com.cn) @@ -247,10 +245,10 @@ public JSONObject(Map map) { /** * Constructs a {@linkplain JSONObject} from JSON data. * @param json the JSON data - * @throws de.ralleytn.simple.json.parser.ParseException if the JSON data is invalid + * @throws JSONParseException if the JSON data is invalid * @since 1.0.0 */ - public JSONObject(String json) throws de.ralleytn.simple.json.parser.ParseException { + public JSONObject(String json) throws JSONParseException { super((JSONObject)new JSONParser().parse(json)); } @@ -259,10 +257,10 @@ public JSONObject(String json) throws de.ralleytn.simple.json.parser.ParseExcept * Constructs a {@linkplain JSONObject} from JSON data read from a {@linkplain Reader}. * @param jsonReader the {@linkplain Reader} with the JSON data * @throws IOException if an I/O error occurred - * @throws de.ralleytn.simple.json.parser.ParseException if the JSON data is invalid + * @throws JSONParseException if the JSON data is invalid * @since 1.0.0 */ - public JSONObject(Reader jsonReader) throws IOException, de.ralleytn.simple.json.parser.ParseException { + public JSONObject(Reader jsonReader) throws IOException, JSONParseException { super((JSONObject)new JSONParser().parse(jsonReader)); } diff --git a/src/de/ralleytn/simple/json/parser/ParseException.java b/src/de/ralleytn/simple/json/JSONParseException.java similarity index 97% rename from src/de/ralleytn/simple/json/parser/ParseException.java rename to src/de/ralleytn/simple/json/JSONParseException.java index 7b04c1e..bac9360 100644 --- a/src/de/ralleytn/simple/json/parser/ParseException.java +++ b/src/de/ralleytn/simple/json/JSONParseException.java @@ -201,7 +201,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package de.ralleytn.simple.json.parser; +package de.ralleytn.simple.json; /** * ParseException explains why and where the error occurs in source JSON text. @@ -209,7 +209,7 @@ * @author FangYidong(fangyidong@yahoo.com.cn) * @author Ralph Niemitz/RalleYTN(ralph.niemitz@gmx.de) */ -public class ParseException extends Exception { +public class JSONParseException extends Exception { private static final long serialVersionUID = -7880698968187728547L; @@ -221,17 +221,17 @@ public class ParseException extends Exception { private Object unexpectedObject; private int position; - public ParseException(int errorType) { + public JSONParseException(int errorType) { this(-1, errorType, null); } - public ParseException(int errorType, Object unexpectedObject) { + public JSONParseException(int errorType, Object unexpectedObject) { this(-1, errorType, unexpectedObject); } - public ParseException(int position, int errorType, Object unexpectedObject) { + public JSONParseException(int position, int errorType, Object unexpectedObject) { this.position = position; this.errorType = errorType; @@ -249,7 +249,7 @@ public void setErrorType(int errorType) { } /** - * @see de.ralleytn.simple.json.parser.JSONParser#getPosition() + * @see de.ralleytn.simple.json.JSONParser#getPosition() * * @return The character position (starting with 0) of the input where the error occurs. */ @@ -264,7 +264,7 @@ public void setPosition(int position) { } /** - * @see de.ralleytn.simple.json.parser.Yytoken + * @see de.ralleytn.simple.json.Yytoken * * @return One of the following base on the value of errorType: * ERROR_UNEXPECTED_CHAR java.lang.Character diff --git a/src/de/ralleytn/simple/json/parser/JSONParser.java b/src/de/ralleytn/simple/json/JSONParser.java similarity index 88% rename from src/de/ralleytn/simple/json/parser/JSONParser.java rename to src/de/ralleytn/simple/json/JSONParser.java index 792d702..0fc09f9 100644 --- a/src/de/ralleytn/simple/json/parser/JSONParser.java +++ b/src/de/ralleytn/simple/json/JSONParser.java @@ -201,7 +201,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package de.ralleytn.simple.json.parser; +package de.ralleytn.simple.json; import java.io.IOException; import java.io.Reader; @@ -210,13 +210,10 @@ import java.util.Map; import java.util.Stack; -import de.ralleytn.simple.json.JSONArray; -import de.ralleytn.simple.json.JSONObject; - /** * Parser for JSON text. Please note that JSONParser is NOT thread-safe. - * @author FangYidong + * @author FangYidong(fangyidong@yahoo.com.cn) * @author Ralph Niemitz/RalleYTN(ralph.niemitz@gmx.de) * @version 1.0.0 * @since 1.0.0 @@ -238,7 +235,7 @@ public class JSONParser { private int status = JSONParser.S_INIT; /** - * Reset the parser to the initial state without resetting the underlying reader. + * Resets the parser to the initial state without resetting the underlying reader. * @since 1.0.0 */ public void reset(){ @@ -249,33 +246,48 @@ public void reset(){ } /** - * Reset the parser to the initial state with a new character reader. - * - * @param in - The new character reader. + * Resets the parser to the initial state with a new character reader. + * @param reader the new character reader. * @throws IOException - * @throws ParseException + * @throws JSONParseException * @since 1.0.0 */ - public void reset(Reader in) { + public void reset(Reader reader) { - this.lexer.yyreset(in); + this.lexer.yyreset(reader); this.reset(); } /** - * @return The position of the beginning of the current token. + * @return the position of the beginning of the current token. + * @since 1.0.0 */ public int getPosition() { return this.lexer.getPosition(); } - public Object parse(String string) throws ParseException { + /** + * + * @param string + * @return + * @throws JSONParseException + * @since 1.0.0 + */ + public Object parse(String string) throws JSONParseException { - return parse(string, (ContainerFactory)null); + return parse(string, (JSONContainerFactory)null); } - public Object parse(String string, ContainerFactory containerFactory) throws ParseException { + /** + * + * @param string + * @param containerFactory + * @return + * @throws JSONParseException + * @since 1.0.0 + */ + public Object parse(String string, JSONContainerFactory containerFactory) throws JSONParseException { try(StringReader in = new StringReader(string)) { @@ -283,13 +295,21 @@ public Object parse(String string, ContainerFactory containerFactory) throws Par } catch(IOException exception){ - throw new ParseException(-1, ParseException.ERROR_UNEXPECTED_EXCEPTION, exception); + throw new JSONParseException(-1, JSONParseException.ERROR_UNEXPECTED_EXCEPTION, exception); } } - public Object parse(Reader in) throws IOException, ParseException { + /** + * + * @param in + * @return + * @throws IOException + * @throws JSONParseException + * @since 1.0.0 + */ + public Object parse(Reader in) throws IOException, JSONParseException { - return this.parse(in, (ContainerFactory)null); + return this.parse(in, (JSONContainerFactory)null); } /** @@ -306,10 +326,10 @@ public Object parse(Reader in) throws IOException, ParseException { * null * * @throws IOException - * @throws ParseException + * @throws JSONParseException */ @SuppressWarnings("unchecked") - public Object parse(Reader reader, ContainerFactory containerFactory) throws IOException, ParseException { + public Object parse(Reader reader, JSONContainerFactory containerFactory) throws IOException, JSONParseException { this.reset(reader); Stack statusStack = new Stack<>(); @@ -354,7 +374,7 @@ public Object parse(Reader reader, ContainerFactory containerFactory) throws IOE } else { - throw new ParseException(this.getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, this.token); + throw new JSONParseException(this.getPosition(), JSONParseException.ERROR_UNEXPECTED_TOKEN, this.token); } } else if(this.status == JSONParser.S_IN_OBJECT) { @@ -474,7 +494,7 @@ public Object parse(Reader reader, ContainerFactory containerFactory) throws IOE if(this.status == JSONParser.S_IN_ERROR) { - throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); + throw new JSONParseException(getPosition(), JSONParseException.ERROR_UNEXPECTED_TOKEN, token); } } while(this.token.type != Yytoken.TYPE_EOF); @@ -484,10 +504,10 @@ public Object parse(Reader reader, ContainerFactory containerFactory) throws IOE throw exception; } - throw new ParseException(this.getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, this.token); + throw new JSONParseException(this.getPosition(), JSONParseException.ERROR_UNEXPECTED_TOKEN, this.token); } - private final void nextToken() throws ParseException, IOException { + private final void nextToken() throws JSONParseException, IOException { this.token = this.lexer.yylex(); @@ -497,7 +517,7 @@ private final void nextToken() throws ParseException, IOException { } } - private final Map createObjectContainer(ContainerFactory containerFactory) { + private final Map createObjectContainer(JSONContainerFactory containerFactory) { if(containerFactory == null) { @@ -514,7 +534,7 @@ private final Map createObjectContainer(ContainerFactory contain return map; } - private final List createArrayContainer(ContainerFactory containerFactory) { + private final List createArrayContainer(JSONContainerFactory containerFactory) { if(containerFactory == null) { @@ -531,12 +551,27 @@ private final List createArrayContainer(ContainerFactory containerFactor return list; } - public void parse(String string, ContentHandler contentHandler) throws ParseException { + /** + * + * @param string + * @param contentHandler + * @throws JSONParseException + * @since 1.0.0 + */ + public void parse(String string, JSONContentHandler contentHandler) throws JSONParseException { this.parse(string, contentHandler, false); } - public void parse(String string, ContentHandler contentHandler, boolean resume) throws ParseException { + /** + * + * @param string + * @param contentHandler + * @param resume + * @throws JSONParseException + * @since 1.0.0 + */ + public void parse(String string, JSONContentHandler contentHandler, boolean resume) throws JSONParseException { try(StringReader reader = new StringReader(string)) { @@ -544,11 +579,19 @@ public void parse(String string, ContentHandler contentHandler, boolean resume) } catch(IOException exception){ - throw new ParseException(-1, ParseException.ERROR_UNEXPECTED_EXCEPTION, exception); + throw new JSONParseException(-1, JSONParseException.ERROR_UNEXPECTED_EXCEPTION, exception); } } - public void parse(Reader reader, ContentHandler contentHandler) throws IOException, ParseException { + /** + * + * @param reader + * @param contentHandler + * @throws IOException + * @throws JSONParseException + * @since 1.0.0 + */ + public void parse(Reader reader, JSONContentHandler contentHandler) throws IOException, JSONParseException { this.parse(reader, contentHandler, false); } @@ -556,7 +599,7 @@ public void parse(Reader reader, ContentHandler contentHandler) throws IOExcepti /** * Stream processing of JSON text. * - * @see ContentHandler + * @see JSONContentHandler * * @param in * @param contentHandler @@ -565,9 +608,10 @@ public void parse(Reader reader, ContentHandler contentHandler) throws IOExcepti * If this method is called for the first time in this instance, isResume will be ignored. * * @throws IOException - * @throws ParseException + * @throws JSONParseException + * @since 1.0.0 */ - public void parse(Reader in, ContentHandler contentHandler, boolean resume) throws IOException, ParseException { + public void parse(Reader in, JSONContentHandler contentHandler, boolean resume) throws IOException, JSONParseException { if(!resume) { @@ -799,18 +843,18 @@ public void parse(Reader in, ContentHandler contentHandler, boolean resume) thro if(this.status == JSONParser.S_IN_ERROR) { - throw new ParseException(this.getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, this.token); + throw new JSONParseException(this.getPosition(), JSONParseException.ERROR_UNEXPECTED_TOKEN, this.token); } } while(this.token.type != Yytoken.TYPE_EOF); - } catch(IOException | ParseException | RuntimeException | Error exception) { + } catch(IOException | JSONParseException | RuntimeException | Error exception) { this.status = JSONParser.S_IN_ERROR; throw exception; } this.status = JSONParser.S_IN_ERROR; - throw new ParseException(this.getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, this.token); + throw new JSONParseException(this.getPosition(), JSONParseException.ERROR_UNEXPECTED_TOKEN, this.token); } } diff --git a/src/de/ralleytn/simple/json/JSONSerializer.java b/src/de/ralleytn/simple/json/JSONSerializer.java index 5586359..bc865e5 100644 --- a/src/de/ralleytn/simple/json/JSONSerializer.java +++ b/src/de/ralleytn/simple/json/JSONSerializer.java @@ -223,26 +223,99 @@ public final class JSONSerializer { private JSONSerializer() {} /** - * Converts a Java object into a {@linkplain JSONObject}. - * @param object the Java object you want to convert - * @return the resulting {@linkplain JSONObject} + * Transfers the data of {@linkplain JSONObject} into a Java object. + * @param json the JSON object containing the data + * @param object the body of the Java object that should be filled * @throws Exception if an error occurs * @since 1.0.0 */ - public static final JSONObject serialize(Object object) throws Exception { + public static final void deserialize(JSONObject json, Object object) throws Exception { Class clazz = object.getClass(); Field[] fields = clazz.getFields(); Method[] methods = clazz.getMethods(); - JSONObject json = new JSONObject(); for(Field field : fields) { - + JSONAttribute annotation = field.getAnnotation(JSONAttribute.class); - if(!Modifier.isTransient(field.getModifiers()) && annotation != null && JSONSerializer.contains(JSONAttribute.Type.GETTER, annotation)) { + if(!Modifier.isTransient(field.getModifiers()) && annotation != null && JSONSerializer.contains(JSONAttribute.Type.SETTER, annotation)) { - JSONSerializer.serialize(json, field.get(object), annotation); + Class targetType = field.getType(); + Object value = json.get(annotation.name()); + + if(value != null) { + + if(float.class.isAssignableFrom(targetType) || Float.class.isAssignableFrom(targetType)) { + + field.set(object, ((Number)value).floatValue()); + + } else if(double.class.isAssignableFrom(targetType) || Double.class.isAssignableFrom(targetType)) { + + field.set(object, ((Number)value).doubleValue()); + + } else if(byte.class.isAssignableFrom(targetType) || Byte.class.isAssignableFrom(targetType)) { + + field.set(object, ((Number)value).byteValue()); + + } else if(short.class.isAssignableFrom(targetType) || Short.class.isAssignableFrom(targetType)) { + + field.set(object, ((Number)value).shortValue()); + + } else if(int.class.isAssignableFrom(targetType) || Integer.class.isAssignableFrom(targetType)) { + + field.set(object, ((Number)value).intValue()); + + } else if(long.class.isAssignableFrom(targetType) || Long.class.isAssignableFrom(targetType)) { + + field.set(object, ((Number)value).longValue()); + + } else if(String.class.isAssignableFrom(targetType) || Number.class.isAssignableFrom(targetType) || Boolean.class.isAssignableFrom(targetType) || boolean.class.isAssignableFrom(targetType)) { + + field.set(object, value); + + } else if(Enum.class.isAssignableFrom(targetType)) { + + for(Object constant : targetType.getEnumConstants()) { + + if(((Enum)constant).name().equals(value.toString())) { + + field.set(object, constant); + break; + } + } + + } else if(targetType.getAnnotation(JSONRoot.class) != null) { + + Object newObject = targetType.newInstance(); + JSONSerializer.deserialize((JSONObject)value, newObject); + field.set(object, newObject); + + } else if(Map.class.isAssignableFrom(targetType)) { + + @SuppressWarnings("unchecked") + Map map = (Map)targetType.newInstance(); + JSONSerializer.deserialize(clazz, object, map, (JSONObject)value); + field.set(object, map); + + } else if(Collection.class.isAssignableFrom(targetType)) { + + @SuppressWarnings("unchecked") + Collection collection = (Collection)targetType.newInstance(); + JSONSerializer.deserialize(clazz, object, collection, (JSONArray)value); + field.set(object, collection); + + } else if(targetType.isArray()) { + + Object newArray = Array.newInstance(targetType.getComponentType(), ((JSONArray)value).size()); + JSONSerializer.deserialize(clazz, object, newArray, ((JSONArray)value)); + field.set(object, newArray); + + } else if(JSONTypeSerializationHandler.class.isAssignableFrom(clazz)) { + + field.set(object, ((JSONTypeSerializationHandler)object).deserialize(targetType, value)); + } + } } } @@ -250,99 +323,378 @@ public static final JSONObject serialize(Object object) throws Exception { JSONAttribute annotation = method.getAnnotation(JSONAttribute.class); - if(!Modifier.isTransient(method.getModifiers()) && annotation != null && JSONSerializer.contains(JSONAttribute.Type.GETTER, annotation)) { + if(!Modifier.isTransient(method.getModifiers()) && annotation != null && JSONSerializer.contains(JSONAttribute.Type.SETTER, annotation)) { + + Class targetType = method.getParameterTypes()[0]; + Object value = json.get(annotation.name()); - JSONSerializer.serialize(json, method.invoke(object), annotation); + if(value != null) { + + if(float.class.isAssignableFrom(targetType) || Float.class.isAssignableFrom(targetType)) { + + method.invoke(object, ((Number)value).floatValue()); + + } else if(double.class.isAssignableFrom(targetType) || Double.class.isAssignableFrom(targetType)) { + + method.invoke(object, ((Number)value).doubleValue()); + + } else if(byte.class.isAssignableFrom(targetType) || Byte.class.isAssignableFrom(targetType)) { + + method.invoke(object, ((Number)value).byteValue()); + + } else if(short.class.isAssignableFrom(targetType) || Short.class.isAssignableFrom(targetType)) { + + method.invoke(object, ((Number)value).shortValue()); + + } else if(int.class.isAssignableFrom(targetType) || Integer.class.isAssignableFrom(targetType)) { + + method.invoke(object, ((Number)value).intValue()); + + } else if(long.class.isAssignableFrom(targetType) || Long.class.isAssignableFrom(targetType)) { + + method.invoke(object, ((Number)value).longValue()); + + } else if(String.class.isAssignableFrom(targetType) || Number.class.isAssignableFrom(targetType) || Boolean.class.isAssignableFrom(targetType) || boolean.class.isAssignableFrom(targetType)) { + + method.invoke(object, value); + + } else if(Enum.class.isAssignableFrom(targetType)) { + + for(Object constant : targetType.getEnumConstants()) { + + if(((Enum)constant).name().equals(value.toString())) { + + method.invoke(object, constant); + break; + } + } + + } else if(targetType.getAnnotation(JSONRoot.class) != null) { + + Object newObject = targetType.newInstance(); + JSONSerializer.deserialize((JSONObject)value, newObject); + method.invoke(object, newObject); + + } else if(Map.class.isAssignableFrom(targetType)) { + + @SuppressWarnings("unchecked") + Map map = (Map)targetType.newInstance(); + JSONSerializer.deserialize(clazz, object, map, (JSONObject)value); + method.invoke(object, map); + + } else if(Collection.class.isAssignableFrom(targetType)) { + + @SuppressWarnings("unchecked") + Collection collection = (Collection)targetType.newInstance(); + JSONSerializer.deserialize(clazz, object, collection, (JSONArray)value); + method.invoke(object, collection); + + } else if(targetType.isArray()) { + + Object newArray = Array.newInstance(targetType.getComponentType(), ((JSONArray)value).size()); + JSONSerializer.deserialize(clazz, object, newArray, ((JSONArray)value)); + method.invoke(object, newArray); + + } else if(JSONTypeSerializationHandler.class.isAssignableFrom(clazz)) { + + method.invoke(object, ((JSONTypeSerializationHandler)object).deserialize(targetType, value)); + } + } } } - - return json; } - /** - * Transfers the data of {@linkplain JSONObject} into a Java object. - * @param json the JSON object containing the data - * @param object the body of the Java object that should be filled - * @throws Exception if an error occurs - * @since 1.0.0 - */ - public static final void deserialize(JSONObject json, Object object) throws Exception { + private static final void deserialize(Class clazz, Object classObject, Collection collection, JSONArray json) throws Exception { - Class clazz = object.getClass(); - Field[] fields = clazz.getFields(); - Method[] methods = clazz.getMethods(); - - for(Field field : fields) { - - JSONAttribute annotation = field.getAnnotation(JSONAttribute.class); + for(Object value : json) { - if(!Modifier.isTransient(field.getModifiers()) && annotation != null && JSONSerializer.contains(JSONAttribute.Type.SETTER, annotation)) { - - if(String.class.isAssignableFrom(field.getType()) || - Boolean.class.isAssignableFrom(field.getType()) || - Number.class.isAssignableFrom(field.getType()) || - boolean.class.isAssignableFrom(field.getType()) || - byte.class.isAssignableFrom(field.getType()) || - short.class.isAssignableFrom(field.getType()) || - int.class.isAssignableFrom(field.getType()) || - long.class.isAssignableFrom(field.getType()) || - float.class.isAssignableFrom(field.getType()) || - double.class.isAssignableFrom(field.getType())) { - - field.set(object, json.get(annotation.name())); + if(value != null) { + + Class type = value.getClass(); + + if(float.class.isAssignableFrom(type) || Float.class.isAssignableFrom(type)) { + + collection.add(((Number)value).floatValue()); + + } else if(double.class.isAssignableFrom(type) || Double.class.isAssignableFrom(type)) { + + collection.add(((Number)value).doubleValue()); + + } else if(byte.class.isAssignableFrom(type) || Byte.class.isAssignableFrom(type)) { + + collection.add(((Number)value).byteValue()); + + } else if(short.class.isAssignableFrom(type) || Short.class.isAssignableFrom(type)) { + + collection.add(((Number)value).shortValue()); + + } else if(int.class.isAssignableFrom(type) || Integer.class.isAssignableFrom(type)) { + + collection.add(((Number)value).intValue()); + + } else if(long.class.isAssignableFrom(type) || Long.class.isAssignableFrom(type)) { + + collection.add(((Number)value).longValue()); + + } else if(String.class.isAssignableFrom(type) || Number.class.isAssignableFrom(type) || Boolean.class.isAssignableFrom(type) || boolean.class.isAssignableFrom(type)) { + + collection.add(value); + + } else if(Enum.class.isAssignableFrom(type)) { + + for(Object constant : type.getEnumConstants()) { + + if(((Enum)constant).name().equals(value.toString())) { + + collection.add(constant); + break; + } + } + + } else if(type.getAnnotation(JSONRoot.class) != null) { + + Object newObject = type.newInstance(); + JSONSerializer.deserialize((JSONObject)value, newObject); + collection.add(newObject); + + } else if(Map.class.isAssignableFrom(type)) { + + @SuppressWarnings("unchecked") + Map newMap = (Map)type.newInstance(); + JSONSerializer.deserialize(clazz, classObject, newMap, (JSONObject)value); + collection.add(newMap); + + } else if(Collection.class.isAssignableFrom(type)) { + + @SuppressWarnings("unchecked") + Collection newCollection = (Collection)type.newInstance(); + JSONSerializer.deserialize(clazz, classObject, newCollection, (JSONArray)value); + collection.add(newCollection); + + } else if(type.isArray()) { + + Object newArray = Array.newInstance(type.getComponentType(), ((JSONArray)value).size()); + JSONSerializer.deserialize(clazz, classObject, newArray, ((JSONArray)value)); + collection.add(newArray); + + } else if(JSONTypeSerializationHandler.class.isAssignableFrom(clazz)) { + + collection.add(((JSONTypeSerializationHandler)classObject).deserialize(type, value)); } + + } else { + + collection.add(value); } } - - for(Method method : methods) { + } + + private static final void deserialize(Class clazz, Object classObject, Map map, JSONObject json) throws Exception { - JSONAttribute annotation = method.getAnnotation(JSONAttribute.class); + for(Object jsonEntry : json.entrySet()) { - if(!Modifier.isTransient(method.getModifiers()) && annotation != null && JSONSerializer.contains(JSONAttribute.Type.SETTER, annotation)) { + Map.Entry entry = (Map.Entry)jsonEntry; + Object value = entry.getValue(); + + if(value != null) { - Class parameterType = method.getParameterTypes()[0]; + Class type = value.getClass(); - if(String.class.isAssignableFrom(parameterType) || - Boolean.class.isAssignableFrom(parameterType) || - Number.class.isAssignableFrom(parameterType) || - boolean.class.isAssignableFrom(parameterType) || - byte.class.isAssignableFrom(parameterType) || - short.class.isAssignableFrom(parameterType) || - int.class.isAssignableFrom(parameterType) || - long.class.isAssignableFrom(parameterType) || - float.class.isAssignableFrom(parameterType) || - double.class.isAssignableFrom(parameterType)) { + if(float.class.isAssignableFrom(type) || Float.class.isAssignableFrom(type)) { + + map.put(entry.getKey(), ((Number)value).floatValue()); + + } else if(double.class.isAssignableFrom(type) || Double.class.isAssignableFrom(type)) { + + map.put(entry.getKey(), ((Number)value).doubleValue()); + + } else if(byte.class.isAssignableFrom(type) || Byte.class.isAssignableFrom(type)) { - method.invoke(object, json.get(annotation.name())); + map.put(entry.getKey(), ((Number)value).byteValue()); - } else if(parameterType.isEnum()) { + } else if(short.class.isAssignableFrom(type) || Short.class.isAssignableFrom(type)) { - for(Object enumConstant : parameterType.getEnumConstants()) { + map.put(entry.getKey(), ((Number)value).shortValue()); + + } else if(int.class.isAssignableFrom(type) || Integer.class.isAssignableFrom(type)) { + + map.put(entry.getKey(), ((Number)value).intValue()); + + } else if(long.class.isAssignableFrom(type) || Long.class.isAssignableFrom(type)) { + + map.put(entry.getKey(), ((Number)value).longValue()); + + } else if(String.class.isAssignableFrom(type) || Number.class.isAssignableFrom(type) || Boolean.class.isAssignableFrom(type) || boolean.class.isAssignableFrom(type)) { + + map.put(entry.getKey(), value); + + } else if(Enum.class.isAssignableFrom(type)) { + + for(Object constant : type.getEnumConstants()) { - if(enumConstant.toString().equals(json.getString(annotation.name()))) { + if(((Enum)constant).name().equals(value.toString())) { - method.invoke(object, enumConstant); + map.put(entry.getKey(), constant); break; } } - } else if(parameterType.isArray()) { + } else if(type.getAnnotation(JSONRoot.class) != null) { + + Object newObject = type.newInstance(); + JSONSerializer.deserialize((JSONObject)value, newObject); + map.put(entry.getKey(), newObject); + + } else if(Map.class.isAssignableFrom(type)) { + + @SuppressWarnings("unchecked") + Map newMap = (Map)type.newInstance(); + JSONSerializer.deserialize(clazz, classObject, newMap, (JSONObject)value); + map.put(entry.getKey(), newMap); - } else if(parameterType.getAnnotation(JSONRoot.class) != null) { + } else if(Collection.class.isAssignableFrom(type)) { + @SuppressWarnings("unchecked") + Collection collection = (Collection)type.newInstance(); + JSONSerializer.deserialize(clazz, classObject, collection, (JSONArray)value); + map.put(entry.getKey(), collection); - } else if(Collection.class.isAssignableFrom(parameterType)) { + } else if(type.isArray()) { + Object newArray = Array.newInstance(type.getComponentType(), ((JSONArray)value).size()); + JSONSerializer.deserialize(clazz, classObject, newArray, ((JSONArray)value)); + map.put(entry.getKey(), newArray); - } else if(Map.class.isAssignableFrom(parameterType)) { + } else if(JSONTypeSerializationHandler.class.isAssignableFrom(clazz)) { + map.put(entry.getKey(), ((JSONTypeSerializationHandler)classObject).deserialize(type, value)); + } + + } else { + + map.put(entry.getKey(), value); + } + } + } + + private static final void deserialize(Class clazz, Object classObject, Object targetObject, JSONArray json) throws Exception { + + Class type = targetObject.getClass().getComponentType(); + + for(int index = 0; index < json.size(); index++) { + + Object value = json.get(index); + + if(float.class.isAssignableFrom(type) || Float.class.isAssignableFrom(type)) { + + Array.set(targetObject, index, ((Number)value).floatValue()); + + } else if(double.class.isAssignableFrom(type) || Double.class.isAssignableFrom(type)) { + + Array.set(targetObject, index, ((Number)value).doubleValue()); + + } else if(byte.class.isAssignableFrom(type) || Byte.class.isAssignableFrom(type)) { + + Array.set(targetObject, index, ((Number)value).byteValue()); + + } else if(short.class.isAssignableFrom(type) || Short.class.isAssignableFrom(type)) { + + Array.set(targetObject, index, ((Number)value).shortValue()); + + } else if(int.class.isAssignableFrom(type) || Integer.class.isAssignableFrom(type)) { + + Array.set(targetObject, index, ((Number)value).intValue()); + + } else if(long.class.isAssignableFrom(type) || Long.class.isAssignableFrom(type)) { + + Array.set(targetObject, index, ((Number)value).longValue()); + + } else if(String.class.isAssignableFrom(type) || Number.class.isAssignableFrom(type) || Boolean.class.isAssignableFrom(type) || boolean.class.isAssignableFrom(type)) { + + Array.set(targetObject, index, value); + + } else if(Enum.class.isAssignableFrom(type)) { + + for(Object constant : type.getEnumConstants()) { + if(((Enum)constant).name().equals(value.toString())) { + + Array.set(targetObject, index, constant); + break; + } } + + } else if(type.getAnnotation(JSONRoot.class) != null) { + + Object newObject = type.newInstance(); + JSONSerializer.deserialize((JSONObject)value, newObject); + Array.set(targetObject, index, newObject); + + } else if(Map.class.isAssignableFrom(type)) { + + @SuppressWarnings("unchecked") + Map map = (Map)type.newInstance(); + JSONSerializer.deserialize(clazz, classObject, map, (JSONObject)value); + Array.set(targetObject, index, map); + + } else if(Collection.class.isAssignableFrom(type)) { + + @SuppressWarnings("unchecked") + Collection collection = (Collection)type.newInstance(); + JSONSerializer.deserialize(clazz, classObject, collection, (JSONArray)value); + Array.set(targetObject, index, collection); + + } else if(type.isArray()) { + + Object newArray = Array.newInstance(type.getComponentType(), ((JSONArray)value).size()); + JSONSerializer.deserialize(clazz, classObject, newArray, ((JSONArray)value)); + Array.set(targetObject, index, newArray); + + } else if(JSONTypeSerializationHandler.class.isAssignableFrom(clazz)) { + + Array.set(targetObject, index, ((JSONTypeSerializationHandler)classObject).deserialize(type, value)); } } } - private static final void serialize(JSONObject json, Object value, JSONAttribute annotation) throws Exception { + /** + * Converts a Java object into a {@linkplain JSONObject}. + * @param object the Java object you want to convert + * @return the resulting {@linkplain JSONObject} + * @throws Exception if an error occurs + * @since 1.0.0 + */ + public static final JSONObject serialize(Object object) throws Exception { + + Class clazz = object.getClass(); + Field[] fields = clazz.getFields(); + Method[] methods = clazz.getMethods(); + JSONObject json = new JSONObject(); + + for(Field field : fields) { + + JSONAttribute annotation = field.getAnnotation(JSONAttribute.class); + + if(!Modifier.isTransient(field.getModifiers()) && annotation != null && JSONSerializer.contains(JSONAttribute.Type.GETTER, annotation)) { + + JSONSerializer.serialize(json, clazz, object, field.getType(), field.get(object), annotation); + } + } + + for(Method method : methods) { + + JSONAttribute annotation = method.getAnnotation(JSONAttribute.class); + + if(!Modifier.isTransient(method.getModifiers()) && annotation != null && JSONSerializer.contains(JSONAttribute.Type.GETTER, annotation)) { + + JSONSerializer.serialize(json, clazz, object, method.getReturnType(), method.invoke(object), annotation); + } + } + + return json; + } + + private static final void serialize(JSONObject json, Class clazz, Object classObject, Class type, Object value, JSONAttribute annotation) throws Exception { if(value instanceof String || value instanceof Number || value instanceof Boolean) {json.put(annotation.name(), value); } else if(value instanceof boolean[]) {json.put(annotation.name(), new JSONArray((boolean[])value)); @@ -352,17 +704,19 @@ private static final void serialize(JSONObject json, Object value, JSONAttribute } else if(value instanceof long[]) {json.put(annotation.name(), new JSONArray((long[])value)); } else if(value instanceof float[]) {json.put(annotation.name(), new JSONArray((float[])value)); } else if(value instanceof double[]) {json.put(annotation.name(), new JSONArray((double[])value)); - } else if(value != null && value.getClass().isArray()) {json.put(annotation.name(), JSONSerializer.getArray(value)); + } else if(value != null && value.getClass().isArray()) {json.put(annotation.name(), JSONSerializer.serializeArray(value, clazz, classObject)); } else if(value != null && value.getClass().getAnnotation(JSONRoot.class) != null) {json.put(annotation.name(), JSONSerializer.serialize(value)); - } else if(value instanceof Collection) {json.put(annotation.name(), JSONSerializer.getArray((Collection)value)); - } else if(value instanceof Map) {json.put(annotation.name(), JSONSerializer.getObject((Map)value)); + } else if(value instanceof Collection) {json.put(annotation.name(), JSONSerializer.serializeArray((Collection)value, clazz, classObject)); + } else if(value instanceof Map) {json.put(annotation.name(), JSONSerializer.serializeObject((Map)value, clazz, classObject)); + } else if(value instanceof Enum) {json.put(annotation.name(), ((Enum)value).name()); + } else if(JSONTypeSerializationHandler.class.isAssignableFrom(clazz)) {json.put(annotation.name(), ((JSONTypeSerializationHandler)classObject).serialize(type, value)); } else { - json.put(annotation.name(), value); + json.put(annotation.name(), value); } } - private static final JSONObject getObject(Map map) throws Exception { + private static final JSONObject serializeObject(Map map, Class clazz, Object classObject) throws Exception { JSONObject json = new JSONObject(); @@ -378,9 +732,12 @@ private static final JSONObject getObject(Map map) throws Exception { } else if(value instanceof float[]) {json.put(entry.getKey(), new JSONArray((float[])value)); } else if(value instanceof double[]) {json.put(entry.getKey(), new JSONArray((double[])value)); } else if(value != null && value.getClass().getAnnotation(JSONRoot.class) != null) {json.put(entry.getKey(), JSONSerializer.serialize(value)); - } else if(value instanceof Map) {json.put(entry.getKey(), JSONSerializer.getObject((Map)value)); - } else if(value instanceof Collection) {json.put(entry.getKey(), JSONSerializer.getArray((Collection)value)); - } else if(value != null && value.getClass().isArray()) {json.put(entry.getKey(), JSONSerializer.getArray(value)); + } else if(value instanceof Map) {json.put(entry.getKey(), JSONSerializer.serializeObject((Map)value, clazz, classObject)); + } else if(value instanceof Collection) {json.put(entry.getKey(), JSONSerializer.serializeArray((Collection)value, clazz, classObject)); + } else if(value != null && value.getClass().isArray()) {json.put(entry.getKey(), JSONSerializer.serializeArray(value, clazz, classObject)); + } else if(value instanceof Enum) {json.put(entry.getKey(), ((Enum)value).name()); + } else if(value instanceof String || value instanceof Boolean || value instanceof Number) {json.put(entry.getKey(), value); + } else if(value != null && JSONTypeSerializationHandler.class.isAssignableFrom(clazz)) {json.put(entry.getKey(), ((JSONTypeSerializationHandler)classObject).serialize(value.getClass(), value)); } else { json.put(entry.getKey(), value); @@ -390,7 +747,7 @@ private static final JSONObject getObject(Map map) throws Exception { return json; } - private static final JSONArray getArray(Collection collection) throws Exception { + private static final JSONArray serializeArray(Collection collection, Class clazz, Object classObject) throws Exception { JSONArray json = new JSONArray(); Iterator iterator = collection.iterator(); @@ -407,9 +764,12 @@ private static final JSONArray getArray(Collection collection) throws Excepti } else if(value instanceof float[]) {json.add(new JSONArray((float[])value)); } else if(value instanceof double[]) {json.add(new JSONArray((double[])value)); } else if(value != null && value.getClass().getAnnotation(JSONRoot.class) != null) {json.add(JSONSerializer.serialize(value)); - } else if(value instanceof Map) {json.add(JSONSerializer.getObject((Map)value)); - } else if(value instanceof Collection) {json.add(JSONSerializer.getArray((Collection)value)); - } else if(value != null && value.getClass().isArray()) {json.add(JSONSerializer.getArray(value)); + } else if(value instanceof Map) {json.add(JSONSerializer.serializeObject((Map)value, clazz, classObject)); + } else if(value instanceof Collection) {json.add(JSONSerializer.serializeArray((Collection)value, clazz, classObject)); + } else if(value != null && value.getClass().isArray()) {json.add(JSONSerializer.serializeArray(value, clazz, classObject)); + } else if(value instanceof Enum) {json.add(((Enum)value).name()); + } else if(value instanceof String || value instanceof Boolean || value instanceof Number) {json.add(value); + } else if(value != null && JSONTypeSerializationHandler.class.isAssignableFrom(clazz)) {((JSONTypeSerializationHandler)classObject).serialize(value.getClass(), value); } else { json.add(value); @@ -419,7 +779,7 @@ private static final JSONArray getArray(Collection collection) throws Excepti return json; } - private static final JSONArray getArray(Object array) throws Exception { + private static final JSONArray serializeArray(Object array, Class clazz, Object classObject) throws Exception { JSONArray json = new JSONArray(); @@ -435,9 +795,12 @@ private static final JSONArray getArray(Object array) throws Exception { } else if(value instanceof float[]) {json.add(new JSONArray((float[])value)); } else if(value instanceof double[]) {json.add(new JSONArray((double[])value)); } else if(value != null && value.getClass().getAnnotation(JSONRoot.class) != null) {json.add(JSONSerializer.serialize(value)); - } else if(value instanceof Map) {json.add(JSONSerializer.getObject((Map)value)); - } else if(value instanceof Collection) {json.add(JSONSerializer.getArray((Collection)value)); - } else if(value != null && value.getClass().isArray()) {json.add(JSONSerializer.getArray(value)); + } else if(value instanceof Map) {json.add(JSONSerializer.serializeObject((Map)value, clazz, classObject)); + } else if(value instanceof Collection) {json.add(JSONSerializer.serializeArray((Collection)value, clazz, classObject)); + } else if(value != null && value.getClass().isArray()) {json.add(JSONSerializer.serializeArray(value, clazz, classObject)); + } else if(value instanceof Enum) {json.add(((Enum)value).name()); + } else if(value instanceof String || value instanceof Boolean || value instanceof Number) {json.add(value); + } else if(value != null && JSONTypeSerializationHandler.class.isAssignableFrom(clazz)) {json.add(((JSONTypeSerializationHandler)classObject).serialize(value.getClass(), value)); } else { json.add(value); diff --git a/src/de/ralleytn/simple/json/parser/ContentHandler.java b/src/de/ralleytn/simple/json/JSONTypeSerializationHandler.java similarity index 79% rename from src/de/ralleytn/simple/json/parser/ContentHandler.java rename to src/de/ralleytn/simple/json/JSONTypeSerializationHandler.java index 0d07ee4..b0a61f8 100644 --- a/src/de/ralleytn/simple/json/parser/ContentHandler.java +++ b/src/de/ralleytn/simple/json/JSONTypeSerializationHandler.java @@ -201,112 +201,31 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package de.ralleytn.simple.json.parser; - -import java.io.IOException; +package de.ralleytn.simple.json; /** - * A simplified and stoppable SAX-like content handler for stream processing of JSON text. - * @see org.xml.sax.ContentHandler - * @see de.ralleytn.simple.json.parser.JSONParser#parse(java.io.Reader, ContentHandler, boolean) - * @author FangYidong(fangyidong@yahoo.com.cn) + * Is needed to manage none-JSON types when serializing or deserializing objects. + * @author Ralph Niemitz/RalleYTN(ralph.niemitz@gmx.de) * @version 1.0.0 * @since 1.0.0 */ -public interface ContentHandler { +public interface JSONTypeSerializationHandler { + /** - * Receive notification of the beginning of JSON processing. - * The parser will invoke this method only once. - * - * @throws ParseException JSONParser will stop and throw the same exception to the caller when receiving this exception. + * Is called when an object is being serialized and a none-JSON type is reached. + * @param type the none-JSON type + * @param value the value + * @return a JSON type value that will be written into the object * @since 1.0.0 */ - public void startJSON() throws ParseException, IOException; - - /** - * Receive notification of the end of JSON processing. - * - * @throws ParseException - */ - public void endJSON() throws ParseException, IOException; - - /** - * Receive notification of the beginning of a JSON object. - * - * @return false if the handler wants to stop parsing after return. - * @throws ParseException - * - JSONParser will stop and throw the same exception to the caller when receiving this exception. - * @see #endJSON - */ - public boolean startObject() throws ParseException, IOException; - - /** - * Receive notification of the end of a JSON object. - * - * @return false if the handler wants to stop parsing after return. - * @throws ParseException - * - * @see #startObject - */ - public boolean endObject() throws ParseException, IOException; - - /** - * Receive notification of the beginning of a JSON object entry. - * - * @param key - Key of a JSON object entry. - * - * @return false if the handler wants to stop parsing after return. - * @throws ParseException - * - * @see #endObjectEntry - */ - public boolean startObjectEntry(String key) throws ParseException, IOException; - - /** - * Receive notification of the end of the value of previous object entry. - * - * @return false if the handler wants to stop parsing after return. - * @throws ParseException - * - * @see #startObjectEntry - */ - public boolean endObjectEntry() throws ParseException, IOException; - - /** - * Receive notification of the beginning of a JSON array. - * - * @return false if the handler wants to stop parsing after return. - * @throws ParseException - * - * @see #endArray - */ - public boolean startArray() throws ParseException, IOException; - - /** - * Receive notification of the end of a JSON array. - * - * @return false if the handler wants to stop parsing after return. - * @throws ParseException - * - * @see #startArray - */ - public boolean endArray() throws ParseException, IOException; + public Object serialize(Class type, Object value); /** - * Receive notification of the JSON primitive values: - * java.lang.String, - * java.lang.Number, - * java.lang.Boolean - * null - * - * @param value - Instance of the following: - * java.lang.String, - * java.lang.Number, - * java.lang.Boolean - * null - * - * @return false if the handler wants to stop parsing after return. - * @throws ParseException + * Is called when the needed type is a none-JSON type. + * @param type the needed type + * @param value the value from the {@linkplain JSONObject} + * @return the value to which the Java object attribute will be set + * @since 1.0.0 */ - public boolean primitive(Object value) throws ParseException, IOException; + public Object deserialize(Class type, Object value); } diff --git a/src/de/ralleytn/simple/json/JSONValue.java b/src/de/ralleytn/simple/json/JSONValue.java index f2b3621..6554d1f 100644 --- a/src/de/ralleytn/simple/json/JSONValue.java +++ b/src/de/ralleytn/simple/json/JSONValue.java @@ -225,8 +225,8 @@ private JSONValue() {} /** * Encode an {@linkplain Object} into JSON text and write it to a {@linkplain Writer}. - *

If this {@linkplain Object} is a {@linkplain Map} or a {@linkplain List}, and it's also a {@linkplain JSONStreamAware} or a {@linkplain JSONAware}, {@linkplain JSONStreamAware} or {@linkplain JSONAware} will be considered firstly.

- * DO NOT call this method from {@link JSONStreamAware#writeJSONString(Writer)} of a class that implements both {@linkplain JSONStreamAware} and ({@linkplain Map} or {@linkplain List}) with + *

If this {@linkplain Object} is a {@linkplain Map} or a {@linkplain Collection}, and it's also a {@linkplain JSONStreamAware} or a {@linkplain JSONAware}, {@linkplain JSONStreamAware} or {@linkplain JSONAware} will be considered firstly.

+ * DO NOT call this method from {@link JSONStreamAware#writeJSONString(Writer)} of a class that implements both {@linkplain JSONStreamAware} and ({@linkplain Map} or {@linkplain Collection}) with * "this" as the first parameter, use {@link JSONObject#writeJSONString(Map, Writer)} or {@link JSONArray#writeJSONString(Collection, Writer)} instead. * @see de.ralleytn.simple.json.JSONObject#writeJSONString(Map, Writer) * @see de.ralleytn.simple.json.JSONArray#writeJSONString(Collection, Writer) @@ -275,7 +275,7 @@ public static void writeJSONString(Object value, Writer writer) throws IOExcepti /** * Convert an {@linkplain Object} to JSON text. - *

If this {@linkplain Object} is a {@linkplain Map} or a {@linkplain List}, and it's also a {@linkplain JSONAware}, {@linkplain JSONAware} it will be considered first.

+ *

If this {@linkplain Object} is a {@linkplain Map} or a {@linkplain Collection}, and it's also a {@linkplain JSONAware}, {@linkplain JSONAware} it will be considered first.

* DO NOT call this method from {@link JSONAware#toJSONString()} of a class that implements both {@linkplain JSONAware} and {@linkplain Map} or {@linkplain Collection} with * "this" as the parameter, use {@link JSONObject#toJSONString(Map)} or {@link JSONArray#toJSONString(Collection)} instead. * @see de.ralleytn.simple.json.JSONObject#toJSONString(Map) diff --git a/src/de/ralleytn/simple/json/parser/Yylex.java b/src/de/ralleytn/simple/json/Yylex.java similarity index 72% rename from src/de/ralleytn/simple/json/parser/Yylex.java rename to src/de/ralleytn/simple/json/Yylex.java index d85b58c..729d44a 100644 --- a/src/de/ralleytn/simple/json/parser/Yylex.java +++ b/src/de/ralleytn/simple/json/Yylex.java @@ -1,32 +1,18 @@ /* The following code was generated by JFlex 1.4.2 */ -package de.ralleytn.simple.json.parser; +package de.ralleytn.simple.json; class Yylex { - /** This character denotes the end of file */ + public static final int YYEOF = -1; - - /** initial size of the lookahead buffer */ private static final int ZZ_BUFFERSIZE = 16384; - - /** lexical states */ public static final int YYINITIAL = 0; public static final int STRING_BEGIN = 2; - - /** - * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l - * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l - * at the beginning of a line - * l is of the form l = 2*k, k a non negative integer - */ private static final int ZZ_LEXSTATE[] = { 0, 0, 1, 1 }; - /** - * Translates characters to character classes - */ private static final String ZZ_CMAP_PACKED = "\11\0\1\7\1\7\2\0\1\7\22\0\1\7\1\0\1\11\10\0"+ "\1\6\1\31\1\2\1\4\1\12\12\3\1\32\6\0\4\1\1\5"+ @@ -34,16 +20,8 @@ class Yylex { "\1\14\5\0\1\23\1\0\1\15\3\0\1\16\1\24\1\17\1\20"+ "\5\0\1\25\1\0\1\26\uff82\0"; - /** - * Translates characters to character classes - */ private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); - - /** - * Translates DFA states to action switch labels. - */ private static final int [] ZZ_ACTION = zzUnpackAction(); - private static final String ZZ_ACTION_PACKED_0 = "\2\0\2\1\1\2\1\3\1\4\3\1\1\5\1\6"+ "\1\7\1\10\1\11\1\12\1\13\1\14\1\15\5\0"+ @@ -59,8 +37,8 @@ class Yylex { } private static int zzUnpackAction(String packed, int offset, int [] result) { - int i = 0; /* index in packed string */ - int j = offset; /* index in unpacked array */ + int i = 0; + int j = offset; int l = packed.length(); while (i < l) { int count = packed.charAt(i++); @@ -70,10 +48,6 @@ private static int zzUnpackAction(String packed, int offset, int [] result) { return j; } - - /** - * Translates a state to a row index in the transition table - */ private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); private static final String ZZ_ROWMAP_PACKED_0 = @@ -92,8 +66,8 @@ private static int zzUnpackAction(String packed, int offset, int [] result) { } private static int zzUnpackRowMap(String packed, int offset, int [] result) { - int i = 0; /* index in packed string */ - int j = offset; /* index in unpacked array */ + int i = 0; + int j = offset; int l = packed.length(); while (i < l) { int high = packed.charAt(i++) << 16; @@ -102,9 +76,6 @@ private static int zzUnpackRowMap(String packed, int offset, int [] result) { return j; } - /** - * The transition table of the DFA - */ private static final int ZZ_TRANS [] = { 2, 2, 3, 4, 2, 2, 2, 5, 2, 6, 2, 2, 7, 8, 2, 9, 2, 2, 2, 2, @@ -176,21 +147,16 @@ private static int zzUnpackRowMap(String packed, int offset, int [] result) { -1, -1, -1, -1, -1, }; - /* error codes */ private static final int ZZ_UNKNOWN_ERROR = 0; private static final int ZZ_NO_MATCH = 1; private static final int ZZ_PUSHBACK_2BIG = 2; - /* error messages for the codes above */ private static final String ZZ_ERROR_MSG[] = { "Unkown internal scanner error", "Error: could not match input", "Error: pushback value was too large" }; - /** - * ZZ_ATTRIBUTE[aState] contains the attributes of state aState - */ private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); private static final String ZZ_ATTRIBUTE_PACKED_0 = @@ -206,8 +172,8 @@ private static int zzUnpackRowMap(String packed, int offset, int [] result) { } private static int zzUnpackAttribute(String packed, int offset, int [] result) { - int i = 0; /* index in packed string */ - int j = offset; /* index in unpacked array */ + int i = 0; + int j = offset; int l = packed.length(); while (i < l) { int count = packed.charAt(i++); @@ -217,77 +183,44 @@ private static int zzUnpackAttribute(String packed, int offset, int [] result) { return j; } - /** the input device */ private java.io.Reader zzReader; - /** the current state of the DFA */ private int zzState; - /** the current lexical state */ private int zzLexicalState = YYINITIAL; - /** this buffer contains the current text to be matched and is - the source of the yytext() string */ private char zzBuffer[] = new char[ZZ_BUFFERSIZE]; - /** the textposition at the last accepting state */ private int zzMarkedPos; - /** the current text position in the buffer */ private int zzCurrentPos; - /** startRead marks the beginning of the yytext() string in the buffer */ private int zzStartRead; - /** endRead marks the last character in the buffer, that has been read - from input */ private int zzEndRead; - /** the number of characters up to the start of the matched text */ private int yychar; - /** zzAtEOF == true <=> the scanner is at the EOF */ private boolean zzAtEOF; - /* user code: */ private StringBuffer sb=new StringBuffer(); int getPosition(){ return yychar; } - - - /** - * Creates a new scanner - * There is also a java.io.InputStream version of this constructor. - * - * @param in the java.io.Reader to read input from. - */ Yylex(java.io.Reader in) { this.zzReader = in; } - /** - * Creates a new scanner. - * There is also java.io.Reader version of this constructor. - * - * @param in the java.io.Inputstream to read input from. - */ Yylex(java.io.InputStream in) { this(new java.io.InputStreamReader(in)); } - /** - * Unpacks the compressed character translation table. - * - * @param packed the packed character translation table - * @return the unpacked character translation table - */ private static char [] zzUnpackCMap(String packed) { char [] map = new char[0x10000]; - int i = 0; /* index in packed string */ - int j = 0; /* index in unpacked array */ + int i = 0; + int j = 0; while (i < 90) { int count = packed.charAt(i++); char value = packed.charAt(i++); @@ -296,38 +229,25 @@ int getPosition(){ return map; } - - /** - * Refills the input buffer. - * - * @return false, iff there was new input. - * - * @exception java.io.IOException if any I/O-Error occurs - */ private boolean zzRefill() throws java.io.IOException { - /* first: make room (if you can) */ if (zzStartRead > 0) { System.arraycopy(zzBuffer, zzStartRead, zzBuffer, 0, zzEndRead-zzStartRead); - /* translate stored positions */ zzEndRead-= zzStartRead; zzCurrentPos-= zzStartRead; zzMarkedPos-= zzStartRead; zzStartRead = 0; } - /* is the buffer big enough? */ if (zzCurrentPos >= zzBuffer.length) { - /* if not: blow it up */ char newBuffer[] = new char[zzCurrentPos*2]; System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length); zzBuffer = newBuffer; } - /* finally: fill the buffer with new input */ int numRead = zzReader.read(zzBuffer, zzEndRead, zzBuffer.length-zzEndRead); @@ -335,7 +255,7 @@ private boolean zzRefill() throws java.io.IOException { zzEndRead+= numRead; return false; } - // unlikely but not impossible: read 0 characters, but not at end of stream + if (numRead == 0) { int c = zzReader.read(); if (c == -1) { @@ -346,14 +266,9 @@ private boolean zzRefill() throws java.io.IOException { } } - // numRead < 0 return true; } - - /** - * Closes the input stream. - */ public final void yyclose() throws java.io.IOException { zzAtEOF = true; /* indicate end of file */ zzEndRead = zzStartRead; /* invalidate buffer */ @@ -362,17 +277,6 @@ public final void yyclose() throws java.io.IOException { zzReader.close(); } - - /** - * Resets the scanner to read from a new input stream. - * Does not close the old reader. - * - * All internal variables are reset, the old input stream - * cannot be reused (internal buffer is discarded and lost). - * Lexical state is set to ZZ_INITIAL. - * - * @param reader the new input stream - */ public final void yyreset(java.io.Reader reader) { zzReader = reader; zzAtEOF = false; @@ -382,71 +286,26 @@ public final void yyreset(java.io.Reader reader) { zzLexicalState = YYINITIAL; } - - /** - * Returns the current lexical state. - */ public final int yystate() { return zzLexicalState; } - - /** - * Enters a new lexical state - * - * @param newState the new lexical state - */ public final void yybegin(int newState) { zzLexicalState = newState; } - - /** - * Returns the text matched by the current regular expression. - */ public final String yytext() { return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead ); } - - /** - * Returns the character at position pos from the - * matched text. - * - * It is equivalent to yytext().charAt(pos), but faster - * - * @param pos the position of the character to fetch. - * A value from 0 to yylength()-1. - * - * @return the character at position pos - */ public final char yycharat(int pos) { return zzBuffer[zzStartRead+pos]; } - - /** - * Returns the length of the matched text region. - */ public final int yylength() { return zzMarkedPos-zzStartRead; } - - /** - * Reports an error that occured while scanning. - * - * In a wellformed scanner (no or only correct usage of - * yypushback(int) and a match-all fallback rule) this method - * will only be called with things that "Can't Possibly Happen". - * If this method is called, something is seriously wrong - * (e.g. a JFlex bug producing a faulty scanner etc.). - * - * Usual syntax/scanner level error handling should be done - * in error fallback rules. - * - * @param errorCode the code of the errormessage to display - */ private void zzScanError(int errorCode) { String message; try { @@ -459,15 +318,6 @@ private void zzScanError(int errorCode) { throw new Error(message); } - - /** - * Pushes the specified amount of characters back into the input stream. - * - * They will be read again by then next call of the scanning method - * - * @param number the number of characters to be read again. - * This number must not be greater than yylength()! - */ public void yypushback(int number) { if ( number > yylength() ) zzScanError(ZZ_PUSHBACK_2BIG); @@ -475,19 +325,10 @@ public void yypushback(int number) { zzMarkedPos -= number; } - - /** - * Resumes scanning until the next regular expression is matched, - * the end of input is encountered or an I/O-Error occurs. - * - * @return the next token - * @exception java.io.IOException if any I/O-Error occurs - */ - public Yytoken yylex() throws java.io.IOException, ParseException { + public Yytoken yylex() throws java.io.IOException, JSONParseException { int zzInput; int zzAction; - // cached fields: int zzCurrentPosL; int zzMarkedPosL; int zzEndReadL = zzEndRead; @@ -592,7 +433,7 @@ else if (zzAtEOF) { } case 33: break; case 1: - { throw new ParseException(yychar, ParseException.ERROR_UNEXPECTED_CHAR, new Character(yycharat(0))); + { throw new JSONParseException(yychar, JSONParseException.ERROR_UNEXPECTED_CHAR, new Character(yycharat(0))); } case 34: break; case 8: @@ -629,7 +470,7 @@ else if (zzAtEOF) { sb.append((char)ch); } catch(Exception e){ - throw new ParseException(yychar, ParseException.ERROR_UNEXPECTED_EXCEPTION, e); + throw new JSONParseException(yychar, JSONParseException.ERROR_UNEXPECTED_EXCEPTION, e); } } case 42: break; diff --git a/src/de/ralleytn/simple/json/parser/Yytoken.java b/src/de/ralleytn/simple/json/Yytoken.java similarity index 99% rename from src/de/ralleytn/simple/json/parser/Yytoken.java rename to src/de/ralleytn/simple/json/Yytoken.java index 31daf63..7b6d91b 100644 --- a/src/de/ralleytn/simple/json/parser/Yytoken.java +++ b/src/de/ralleytn/simple/json/Yytoken.java @@ -201,9 +201,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package de.ralleytn.simple.json.parser; +package de.ralleytn.simple.json; -/** +/* * @author FangYidong(fangyidong@yahoo.com.cn) * @author Ralph Niemitz/RalleYTN(ralph.niemitz@gmx.de) * @version 1.0.0 diff --git a/src/test/JSONFormatterTest.java b/src/test/JSONFormatterTest.java deleted file mode 100644 index 83d0455..0000000 --- a/src/test/JSONFormatterTest.java +++ /dev/null @@ -1,21 +0,0 @@ -package test; - -import de.ralleytn.simple.json.JSONFormatter; - -public class JSONFormatterTest { - - public static void main(String[] args) { - - // MINIMIZE - String json = "{\n\t\"testValue1\":\"Hello there!\",\n \"testValue2\":300,\n\"testValue3\":{}}"; - System.out.println("==== ORIGINAL ===="); - System.out.println(json); - String minimized = JSONFormatter.minimize(json); - System.out.println(); - System.out.println("==== MINIMIZED ===="); - System.out.println(minimized); - System.out.println(); - System.out.println("==== FORMATTED ===="); - System.out.println(JSONFormatter.format(minimized)); - } -} diff --git a/src/test/JSONObjectTest.java b/src/test/JSONObjectTest.java deleted file mode 100644 index 47c9a51..0000000 --- a/src/test/JSONObjectTest.java +++ /dev/null @@ -1,16 +0,0 @@ -package test; - -import java.text.ParseException; -import java.time.Month; - -import de.ralleytn.simple.json.JSONObject; - -public class JSONObjectTest { - - public static void main(String[] args) throws ParseException { - - JSONObject object = new JSONObject(); - object.put("date", "2000-01-01 01:01:00"); - object.put("month", Month.FEBRUARY); - } -} diff --git a/src/test/JSONParserTest.java b/src/test/JSONParserTest.java deleted file mode 100644 index 9ab393d..0000000 --- a/src/test/JSONParserTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package test; - -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; - -import de.ralleytn.simple.json.JSONArray; -import de.ralleytn.simple.json.parser.JSONParser; -import de.ralleytn.simple.json.parser.ParseException; - -public class JSONParserTest { - - public static void main(String[] args) throws FileNotFoundException, IOException, ParseException { - - JSONParser parser = new JSONParser(); - JSONArray array = (JSONArray)parser.parse(new FileReader("test1.json")); - System.out.println(array); - } -} diff --git a/src/test/JSONSerializerTest.java b/src/test/JSONSerializerTest.java deleted file mode 100644 index 4fb2284..0000000 --- a/src/test/JSONSerializerTest.java +++ /dev/null @@ -1,28 +0,0 @@ -package test; - -import java.time.LocalDate; - -import de.ralleytn.simple.json.JSONFormatter; -import de.ralleytn.simple.json.JSONObject; -import de.ralleytn.simple.json.JSONSerializer; -import test.Person.Hobby; - -public class JSONSerializerTest { - - public static void main(String[] args) throws Exception { - - Person person = new Person(); - person.setFirstName("Ralph"); - person.setLastName("Niemitz"); - person.setBirthDate(LocalDate.of(1998, 6, 24)); - person.setHobby(Hobby.PROGRAMMING); - person.setMonthlyIncome(600); - person.setFriends(new Person[] {new Person(), new Person()}); - - JSONObject json = JSONSerializer.serialize(person); - Person newPerson = new Person(); - JSONSerializer.deserialize(json, newPerson); - - System.out.println(JSONFormatter.format(JSONSerializer.serialize(newPerson).toJSONString())); - } -} \ No newline at end of file diff --git a/src/test/Person.java b/src/test/Person.java deleted file mode 100644 index 6b5679f..0000000 --- a/src/test/Person.java +++ /dev/null @@ -1,97 +0,0 @@ -package test; - -import java.time.LocalDate; - -import de.ralleytn.simple.json.JSONAttribute; -import de.ralleytn.simple.json.JSONRoot; - -@JSONRoot -public class Person { - - private String firstName; - private String lastName; - private LocalDate birthDate; - private float monthlyIncome; - private Hobby hobby; - private Person[] friends; - - @JSONAttribute(name = "first_name", type = JSONAttribute.Type.SETTER) - public void setFirstName(String firstName) { - - this.firstName = firstName; - } - - @JSONAttribute(name = "last_name", type = JSONAttribute.Type.SETTER) - public void setLastName(String lastName) { - - this.lastName = lastName; - } - - @JSONAttribute(name = "birth_date", type = JSONAttribute.Type.SETTER) - public void setBirthDate(LocalDate birthDate) { - - this.birthDate = birthDate; - } - - @JSONAttribute(name = "monthly_income", type = JSONAttribute.Type.SETTER) - public void setMonthlyIncome(float monthlyIncome) { - - this.monthlyIncome = monthlyIncome; - } - - @JSONAttribute(name = "hobby", type = JSONAttribute.Type.SETTER) - public void setHobby(Hobby hobby) { - - this.hobby = hobby; - } - - @JSONAttribute(name = "friends", type = JSONAttribute.Type.SETTER) - public void setFriends(Person[] friends) { - - this.friends = friends; - } - - @JSONAttribute(name = "first_name", type = JSONAttribute.Type.GETTER) - public String getFirstName() { - - return this.firstName; - } - - @JSONAttribute(name = "last_name", type = JSONAttribute.Type.GETTER) - public String getLastName() { - - return this.lastName; - } - - @JSONAttribute(name = "birth_date", type = JSONAttribute.Type.GETTER) - public LocalDate getBirthDate() { - - return this.birthDate; - } - - @JSONAttribute(name = "monthly_income", type = JSONAttribute.Type.GETTER) - public float getMonthlyIncome() { - - return this.monthlyIncome; - } - - @JSONAttribute(name = "hobby", type = JSONAttribute.Type.GETTER) - public Hobby getHobby() { - - return this.hobby; - } - - @JSONAttribute(name = "friends", type = JSONAttribute.Type.GETTER) - public Person[] getFriends() { - - return this.friends; - } - - public static enum Hobby { - - PROGRAMMING, - GAMING, - DRAWING, - ANIME; - } -} diff --git a/src/test/Product.java b/src/test/Product.java deleted file mode 100644 index d973559..0000000 --- a/src/test/Product.java +++ /dev/null @@ -1,25 +0,0 @@ -package test; - -import java.util.Date; - -import de.ralleytn.simple.json.JSONAttribute; -import de.ralleytn.simple.json.JSONRoot; - -@JSONRoot -public class Product { - - @JSONAttribute(name = "price") - public float price; - - @JSONAttribute(name = "name") - public String name; - - @JSONAttribute(name = "stock") - public int stock; - - @JSONAttribute(name = "next") - public Product next; - - @JSONAttribute(name = "date") - public Date date = new Date(); -}