pax_global_header00006660000000000000000000000064127735007500014520gustar00rootroot0000000000000052 comment=b2313f9f8ab4db3ac7e965f9db12bccc1ad8d552 mjson-1.4.0/000077500000000000000000000000001277350075000126505ustar00rootroot00000000000000mjson-1.4.0/.gitignore000066400000000000000000000001161277350075000146360ustar00rootroot00000000000000# Maven / Eclipse /target/ .classpath .project .settings # Idea .idea *.iml mjson-1.4.0/LICENSE.txt000066400000000000000000000261361277350075000145030ustar00rootroot00000000000000 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. mjson-1.4.0/README.md000066400000000000000000000040171277350075000141310ustar00rootroot00000000000000mJson is an extremely lightweight Java JSON library with a very concise API. The source code is a single Java file. The license is Apache 2.0. Because of its tiny size, it's well-suited for any application aiming at a small footprint such as mobile/Android applications. It was originally developed in the context of the [OpenCiRM](https://github.com/sharegov/opencirm) project. There is a graph database based persistent layer for mJson implemented at the [HyperGraphDB Project](http://hypergraphdb.org/learn?page=Json&project=hypergraphdb). This means you can transparently persist and query JSON documents like in document-oriented databases (MongoDB, CouchDB), but you don't have split documents into separate collection or create special purposes indices since all documents and properties are automatically interlinked. ### Features * Full support for [JSON Schema Draft 4](http://json-schema.org/) validation * Single universal type - everything is a `Json`, no type casting * Single factory method, no new operators, just call `Json.make(anything here)` * Fast, hand-coded parsing * Designed as a general purpose data structure for use in Java * Parent pointers and `up` method to traverse the JSON structure * Concise methods to read (`Json.at`), modify (`Json.set`, `Json.add`), duplicate (`Json.dup`), merge (`Json.with`) * Methods for type-check (e.g. `Json.isString()`) and access to underlying Java value (e.g. `Json.asString()`) * Method chaining * Pluggable factory to build your own support for arbitrary Java<->Json mapping * 1 Java file is the whole library with no external dependencies ### API Tour Go see a **[Complete Tour of the API](https://github.com/bolerio/mjson/wiki/A-Tour-of-the-API)** Read my tutorial blog on **[JSON Schema](http://www.kobrix.blogspot.com/2014/09/jayson-skima-validating-javascript.html)** ### Wish List (get in touch if you want to help!) 1. Traversal API, with pattern-matching 2. Extend JSON Schema support for template generation **[Goto mJson Official Website](http://bolerio.github.io/mjson/)** mjson-1.4.0/changelog.txt000066400000000000000000000001051277350075000153340ustar00rootroot000000000000001.3 Changes: - Check for null property names in ObjectJson.set mjson-1.4.0/pom.xml000066400000000000000000000132751277350075000141750ustar00rootroot00000000000000 4.0.0 org.sonatype.oss oss-parent 7 bundle ${project.groupId}-${project.artifactId};singleton:=true mjson ${packageit} org.sharegov mjson Minimal JSON Library 1.4.0 http://sharegov.org/mjson A concise, loosely typed Java API for Json The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo boris Borislav Iordanov borislav.iordanov@gmail.com ossrh https://oss.sonatype.org/content/repositories/snapshots ossrh https://oss.sonatype.org/service/local/staging/deploy/maven2/ target target/classes ${project.artifactId}-${project.version} target/test-classes src/java org.apache.maven.plugins maven-compiler-plugin 2.0.2 1.7 1.7 org.apache.maven.plugins maven-source-plugin attach-sources jar org.apache.maven.plugins maven-javadoc-plugin -Xdoclint:none attach-javadocs jar org.apache.maven.plugins maven-deploy-plugin true org.sonatype.plugins nexus-staging-maven-plugin https://oss.sonatype.org/ ossrh default-deploy deploy deploy org.apache.maven.plugins maven-surefire-plugin 2.17 src/test/java ${project.basedir}/src/test/resources org.apache.felix maven-bundle-plugin 2.5.3 true META-INF ${project.groupId}-${project.artifactId};singleton:=true ${project.name} ${project.version} mjson biz.aQute.bnd bndlib 2.4.0 junit junit 4.12 mjson-1.4.0/src/000077500000000000000000000000001277350075000134375ustar00rootroot00000000000000mjson-1.4.0/src/java/000077500000000000000000000000001277350075000143605ustar00rootroot00000000000000mjson-1.4.0/src/java/mjson/000077500000000000000000000000001277350075000155065ustar00rootroot00000000000000mjson-1.4.0/src/java/mjson/Json.java000077500000000000000000003170511277350075000172740ustar00rootroot00000000000000/* * Copyright (C) 2011 Miami-Dade County. * * 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. * * Note: this file incorporates source code from 3d party entities. Such code * is copyrighted by those entities as indicated below. */ package mjson; import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import java.net.URI; import java.net.URL; import java.text.CharacterIterator; import java.text.StringCharacterIterator; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.IdentityHashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; //import java.util.function.Function; import java.util.regex.Pattern; /** * *

* Represents a JSON (JavaScript Object Notation) entity. For more information about JSON, please see * http://www.json.org. *

* *

* A JSON entity can be one of several things: an object (set of name/Json entity pairs), an array (a list of * other JSON entities), a string, a number, a boolean or null. All of those are represented as Json * instances. Each of the different types of entities supports a different set of operations. However, this class * unifies all operations into a single interface so in Java one is always dealing with a single object type: this class. * The approach effectively amounts to dynamic typing where using an unsupported operation won't be detected at * compile time, but will throw a runtime {@link UnsupportedOperationException}. It simplifies working with JSON * structures considerably and it leads to shorter at cleaner Java code. It makes much easier to work * with JSON structure without the need to convert to "proper" Java representation in the form of * POJOs and the like. When traversing a JSON, there's no need to type-cast at each step because there's * only one type: Json. *

* *

* One can examine the concrete type of a Json with one of the isXXX methods: * {@link #isObject()}, {@link #isArray()},{@link #isNumber()},{@link #isBoolean()},{@link #isString()}, * {@link #isNull()}. *

* *

* The underlying representation of a given Json instance can be obtained by calling * the generic {@link #getValue()} method or one of the asXXX methods such * as {@link #asBoolean()} or {@link #asString()} etc. * JSON objects are represented as Java {@link Map}s while JSON arrays are represented as Java * {@link List}s. Because those are mutable aggregate structures, there are two versions of the * corresponding asXXX methods: {@link #asMap()} which performs a deep copy of the underlying * map, unwrapping every nested Json entity to its Java representation and {@link #asJsonMap()} which * simply return the map reference. Similarly there are {@link #asList()} and {@link #asJsonList()}. *

* *

Constructing and Modifying JSON Structures

* *

* There are several static factory methods in this class that allow you to create new * Json instances: *

* * * * * * * * * * * * * * * * * * * * * * * *
{@link #read(String)}Parse a JSON string and return the resulting Json instance. The syntax * recognized is as defined in http://www.json.org. *
{@link #make(Object)}Creates a Json instance based on the concrete type of the parameter. The types * recognized are null, numbers, primitives, String, Map, Collection, Java arrays * and Json itself.
{@link #nil()}Return a Json instance representing JSON null.
{@link #object()}Create and return an empty JSON object.
{@link #object(Object...)}Create and return a JSON object populated with the key/value pairs * passed as an argument sequence. Each even parameter becomes a key (via * toString) and each odd parameter is converted to a Json * value.
{@link #array()}Create and return an empty JSON array.
{@link #array(Object...)}Create and return a JSON array from the list of arguments.
* *

* To customize how Json elements are represented and to provide your own version of the * {@link #make(Object)} method, you create an implementation of the {@link Factory} interface * and configure it either globally with the {@link #setGlobalFactory(Factory)} method or * on a per-thread basis with the {@link #attachFactory(Factory)}/{@link #detachFactory()} * methods. *

* *

* If a Json instance is an object, you can set its properties by * calling the {@link #set(String, Object)} method which will add a new property or replace an existing one. * Adding elements to an array Json is done with the {@link #add(Object)} method. * Removing elements by their index (or key) is done with the {@link #delAt(int)} (or * {@link #delAt(String)}) method. You can also remove an element from an array without * knowing its index with the {@link #remove(Object)} method. All these methods return the * Json instance being manipulated so that method calls can be chained. * If you want to remove an element from an object or array and return the removed element * as a result of the operation, call {@link #atDel(int)} or {@link #atDel(String)} instead. *

* *

* If you want to add properties to an object in bulk or append a sequence of elements to array, * use the {@link #with(Json, Json...opts)} method. When used on an object, this method expects another * object as its argument and it will copy all properties of that argument into itself. Similarly, * when called on array, the method expects another array and it will append all elements of its * argument to itself. *

* *

* To make a clone of a Json object, use the {@link #dup()} method. This method will create a new * object even for the immutable primitive Json types. Objects and arrays are cloned * (i.e. duplicated) recursively. *

* *

Navigating JSON Structures

* *

* The {@link #at(int)} method returns the array element at the specified index and the * {@link #at(String)} method does the same for a property of an object instance. You can * use the {@link #at(String, Object)} version to create an object property with a default * value if it doesn't exist already. *

* *

* To test just whether a Json object has a given property, use the {@link #has(String)} method. To test * whether a given object property or an array elements is equal to a particular value, use the * {@link #is(String, Object)} and {@link #is(int, Object)} methods respectively. Those methods return * true if the given named property (or indexed element) is equal to the passed in Object as the second * parameter. They return false if an object doesn't have the specified property or an index array is out * of bounds. For example is(name, value) is equivalent to 'has(name) && at(name).equals(make(value))'. *

* *

* To help in navigating JSON structures, instances of this class contain a reference to the * enclosing JSON entity (object or array) if any. The enclosing entity can be accessed * with {@link #up()} method. *

* *

* The combination of method chaining when modifying Json instances and * the ability to navigate "inside" a structure and then go back to the enclosing * element lets one accomplish a lot in a single Java statement, without the need * of intermediary variables. Here for example how the following JSON structure can * be created in one statement using chained calls: *

* *

 * {"menu": {
 * "id": "file",
 * "value": "File",
 * "popup": {
 *   "menuitem": [
 *     {"value": "New", "onclick": "CreateNewDoc()"},
 *     {"value": "Open", "onclick": "OpenDoc()"},
 *     {"value": "Close", "onclick": "CloseDoc()"}
 *   ]
 * }
 * "position": 0
 * }}
 * 
* *

 * import mjson.Json;
 * import static mjson.Json.*;
 * ...
 * Json j = object()
 *  .at("menu", object())
 *    .set("id", "file") 
 *    .set("value", "File")
 *    .at("popup", object())
 *      .at("menuitem", array())
 *        .add(object("value", "New", "onclick", "CreateNewDoc()"))
 *        .add(object("value", "Open", "onclick", "OpenDoc()"))
 *        .add(object("value", "Close", "onclick", "CloseDoc()"))
 *        .up()
 *      .up()
 *    .set("position", 0)
 *  .up();       
 * ...
 * 
* *

* If there's no danger of naming conflicts, a static import of the factory methods ( * import static json.Json.*;) would reduce typing even further and make the code more * readable. *

* *

Converting to String

* *

* To get a compact string representation, simply use the {@link #toString()} method. If you * want to wrap it in a JavaScript callback (for JSON with padding), use the {@link #pad(String)} * method. *

* *

Validating with JSON Schema

* *

* Since version 1.3, mJson supports JSON Schema, draft 4. A schema is represented by the internal * class {@link mjson.Json.Schema}. To perform a validation, you have a instantiate a Json.Schema * using the factory method {@link mjson.Json.Schema} and then call its validate method * on a JSON instance: *

* *

 * import mjson.Json;
 * import static mjson.Json.*;
 * ...
 * Json inputJson = Json.read(inputString);
 * Json schema = Json.schema(new URI("http://mycompany.com/schemas/model"));
 * Json errors = schema.validate(inputJson);
 * for (Json error : errors.asJsonList())
 * 	   System.out.println("Validation error " + err);
 * 
* @author Borislav Iordanov * @version 1.4 */ public class Json implements java.io.Serializable { private static final long serialVersionUID = 1L; /** *

* This interface defines how Json instances are constructed. There is a * default implementation for each kind of Json value, but you can provide * your own implementation. For example, you might want a different representation of * an object than a regular HashMap. Or you might want string comparison to be * case insensitive. *

* *

* In addition, the {@link #make(Object)} method allows you plug-in your own mapping * of arbitrary Java objects to Json instances. You might want to implement * a Java Beans to JSON mapping or any other JSON serialization that makes sense in your * project. *

* *

* To avoid implementing all methods in that interface, you can extend the {@link DefaultFactory} * default implementation and simply overwrite the ones you're interested in. *

* *

* The factory implementation used by the Json classes is specified simply by calling * the {@link #setGlobalFactory(Factory)} method. The factory is a static, global variable by default. * If you need different factories in different areas of a single application, you may attach them * to different threads of execution using the {@link #attachFactory(Factory)}. Recall a separate * copy of static variables is made per ClassLoader, so for example in a web application context, that * global factory can be different for each web application (as Java web servers usually use a separate * class loader per application). Thread-local factories are really a provision for special cases. *

* * @author Borislav Iordanov * */ public static interface Factory { /** * Construct and return an object representing JSON null. Implementations are * free to cache a return the same instance. The resulting value must return * true from isNull() and null from * getValue(). * * @return The representation of a JSON null value. */ Json nil(); /** * Construct and return a JSON boolean. The resulting value must return * true from isBoolean() and the passed * in parameter from getValue(). * @param value The boolean value. * @return A JSON with isBoolean() == true. Implementations * are free to cache and return the same instance for true and false. */ Json bool(boolean value); /** * Construct and return a JSON string. The resulting value must return * true from isString() and the passed * in parameter from getValue(). * @param value The string to wrap as a JSON value. * @return A JSON element with the given string as a value. */ Json string(String value); /** * Construct and return a JSON number. The resulting value must return * true from isNumber() and the passed * in parameter from getValue(). * * @param value The numeric value. * @return Json instance representing that value. */ Json number(Number value); /** * Construct and return a JSON object. The resulting value must return * true from isObject() and an implementation * of java.util.Map from getValue(). * * @return An empty JSON object. */ Json object(); /** * Construct and return a JSON object. The resulting value must return * true from isArray() and an implementation * of java.util.List from getValue(). * * @return An empty JSON array. */ Json array(); /** * Construct and return a JSON object. The resulting value can be of any * JSON type. The method is responsible for examining the type of its * argument and performing an appropriate mapping to a Json * instance. * * @param anything An arbitray Java object from which to construct a Json * element. * @return The newly constructed Json instance. */ Json make(Object anything); } public static interface Function { /** * Applies this function to the given argument. * * @param t the function argument * @return the function result */ R apply(T t); } /** *

* Represents JSON schema - a specific data format that a JSON entity must * follow. The idea of a JSON schema is very similar to XML. Its main purpose * is validating input. *

* *

* More information about the various JSON schema specifications can be * found at http://json-schema.org. JSON Schema is an IETF draft (v4 currently) and * our implementation follows this set of specifications. A JSON schema is specified * as a JSON object that contains keywords defined by the specification. Here are * a few introductory materials: *

*

* @author Borislav Iordanov * */ public static interface Schema { /** *

* Validate a JSON document according to this schema. The validations attempts to * proceed even in the face of errors. The return value is always a Json.object * containing the boolean property ok. When ok is true, * the return object contains nothing else. When it is false, the return object * contains a property errors which is an array of error messages for all * detected schema violations. *

* * @param document The input document. * @return {"ok":true} or {"ok":false, errors:["msg1", "msg2", ...]} */ Json validate(Json document); /** *

Return the JSON representation of the schema.

*/ Json toJson(); /** *

Possible options are: ignoreDefaults:true|false. *

* @return A newly created Json conforming to this schema. */ //Json generate(Json options); } static String fetchContent(URL url) { java.io.Reader reader = null; try { reader = new java.io.InputStreamReader((java.io.InputStream)url.getContent()); StringBuilder content = new StringBuilder(); char [] buf = new char[1024]; for (int n = reader.read(buf); n > -1; n = reader.read(buf)) content.append(buf, 0, n); return content.toString(); } catch (Exception ex) { throw new RuntimeException(ex); } finally { if (reader != null) try { reader.close(); } catch (Throwable t) { } } } static Json resolvePointer(String pointerRepresentation, Json top) { String [] parts = pointerRepresentation.split("/"); Json result = top; for (String p : parts) { // TODO: unescaping and decoding if (p.length() == 0) continue; p = p.replace("~1", "/").replace("~0", "~"); if (result.isArray()) result = result.at(Integer.parseInt(p)); else if (result.isObject()) result = result.at(p); else throw new RuntimeException("Can't resolve pointer " + pointerRepresentation + " on document " + top.toString(200)); } return result; } static URI makeAbsolute(URI base, String ref) throws Exception { URI refuri; if (base != null && base.getAuthority() != null && !new URI(ref).isAbsolute()) { StringBuilder sb = new StringBuilder(); if (base.getScheme() != null) sb.append(base.getScheme()).append("://"); sb.append(base.getAuthority()); if (!ref.startsWith("/")) { if (ref.startsWith("#")) sb.append(base.getPath()); else { int slashIdx = base.getPath().lastIndexOf('/'); sb.append(slashIdx == -1 ? base.getPath() : base.getPath().substring(0, slashIdx)).append("/"); } } refuri = new URI(sb.append(ref).toString()); } else if (base != null) refuri = base.resolve(ref); else refuri = new URI(ref); return refuri; } static Json resolveRef(URI base, Json refdoc, URI refuri, Map resolved, Map expanded, Function uriResolver) throws Exception { if (refuri.isAbsolute() && (base == null || !base.isAbsolute() || !base.getScheme().equals(refuri.getScheme()) || !Objects.equals(base.getHost(), refuri.getHost()) || base.getPort() != refuri.getPort() || !base.getPath().equals(refuri.getPath()))) { URI docuri = null; refuri = refuri.normalize(); if (refuri.getHost() == null) docuri = new URI(refuri.getScheme() + ":" + refuri.getPath()); else docuri = new URI(refuri.getScheme() + "://" + refuri.getHost() + ((refuri.getPort() > -1) ? ":" + refuri.getPort() : "") + refuri.getPath()); refdoc = uriResolver.apply(docuri); refdoc = expandReferences(refdoc, refdoc, docuri, resolved, expanded, uriResolver); } if (refuri.getFragment() == null) return refdoc; else return resolvePointer(refuri.getFragment(), refdoc); } /** *

* Replace all JSON references, as per the http://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03 * specification, by their referants. *

* @param json * @param duplicate * @param done * @return */ static Json expandReferences(Json json, Json topdoc, URI base, Map resolved, Map expanded, Function uriResolver) throws Exception { if (expanded.containsKey(json)) return json; if (json.isObject()) { if (json.has("id") && json.at("id").isString()) // change scope of nest references { base = base.resolve(json.at("id").asString()); } if (json.has("$ref")) { URI refuri = makeAbsolute(base, json.at("$ref").asString()); // base.resolve(json.at("$ref").asString()); Json ref = resolved.get(refuri.toString()); if (ref == null) { ref = Json.object(); resolved.put(refuri.toString(), ref); ref.with(resolveRef(base, topdoc, refuri, resolved, expanded, uriResolver)); } json = ref; } else { for (Map.Entry e : json.asJsonMap().entrySet()) json.set(e.getKey(), expandReferences(e.getValue(), topdoc, base, resolved, expanded, uriResolver)); } } else if (json.isArray()) { for (int i = 0; i < json.asJsonList().size(); i++) json.set(i, expandReferences(json.at(i), topdoc, base, resolved, expanded, uriResolver)); } expanded.put(json, json); return json; } static class DefaultSchema implements Schema { static interface Instruction extends Function{} static Json maybeError(Json errors, Json E) { return E == null ? errors : (errors == null ? Json.array() : errors).with(E, new Json[0]); } // Anything is valid schema static Instruction any = new Instruction() { public Json apply(Json param) { return null; } }; // Type validation class IsObject implements Instruction { public Json apply(Json param) { return param.isObject() ? null : Json.make(param.toString(maxchars)); } } class IsArray implements Instruction { public Json apply(Json param) { return param.isArray() ? null : Json.make(param.toString(maxchars)); } } class IsString implements Instruction { public Json apply(Json param) { return param.isString() ? null : Json.make(param.toString(maxchars)); } } class IsBoolean implements Instruction { public Json apply(Json param) { return param.isBoolean() ? null : Json.make(param.toString(maxchars)); } } class IsNull implements Instruction { public Json apply(Json param) { return param.isNull() ? null : Json.make(param.toString(maxchars)); } } class IsNumber implements Instruction { public Json apply(Json param) { return param.isNumber() ? null : Json.make(param.toString(maxchars)); } } class IsInteger implements Instruction { public Json apply(Json param) { return param.isNumber() && ((Number)param.getValue()) instanceof Integer ? null : Json.make(param.toString(maxchars)); } } class CheckString implements Instruction { int min = 0, max = Integer.MAX_VALUE; Pattern pattern; public Json apply(Json param) { Json errors = null; if (!param.isString()) return errors; String s = param.asString(); final int size = s.codePointCount(0, s.length()); if (size < min || size > max) errors = maybeError(errors,Json.make("String " + param.toString(maxchars) + " has length outside of the permitted range [" + min + "," + max + "].")); if (pattern != null && !pattern.matcher(s).matches()) errors = maybeError(errors,Json.make("String " + param.toString(maxchars) + " does not match regex " + pattern.toString())); return errors; } } class CheckNumber implements Instruction { double min = Double.NaN, max = Double.NaN, multipleOf = Double.NaN; boolean exclusiveMin = false, exclusiveMax = false; public Json apply(Json param) { Json errors = null; if (!param.isNumber()) return errors; double value = param.asDouble(); if (!Double.isNaN(min) && (value < min || exclusiveMin && value == min)) errors = maybeError(errors,Json.make("Number " + param + " is below allowed minimum " + min)); if (!Double.isNaN(max) && (value > max || exclusiveMax && value == max)) errors = maybeError(errors,Json.make("Number " + param + " is above allowed maximum " + max)); if (!Double.isNaN(multipleOf) && (value / multipleOf) % 1 != 0) errors = maybeError(errors,Json.make("Number " + param + " is not a multiple of " + multipleOf)); return errors; } } class CheckArray implements Instruction { int min = 0, max = Integer.MAX_VALUE; Boolean uniqueitems = null; Instruction additionalSchema = any; Instruction schema; ArrayList schemas; public Json apply(Json param) { Json errors = null; if (!param.isArray()) return errors; if (schema == null && schemas == null && additionalSchema == null) // no schema specified return errors; int size = param.asJsonList().size(); for (int i = 0; i < size; i++) { Instruction S = schema != null ? schema : (schemas != null && i < schemas.size()) ? schemas.get(i) : additionalSchema; if (S == null) errors = maybeError(errors,Json.make("Additional items are not permitted: " + param.at(i) + " in " + param.toString(maxchars))); else errors = maybeError(errors, S.apply(param.at(i))); if (uniqueitems != null && uniqueitems && param.asJsonList().lastIndexOf(param.at(i)) > i) errors = maybeError(errors,Json.make("Element " + param.at(i) + " is duplicate in array.")); if (errors != null && !errors.asJsonList().isEmpty()) break; } if (size < min || size > max) errors = maybeError(errors,Json.make("Array " + param.toString(maxchars) + " has number of elements outside of the permitted range [" + min + "," + max + "].")); return errors; } } class CheckPropertyPresent implements Instruction { String propname; public CheckPropertyPresent(String propname) { this.propname = propname; } public Json apply(Json param) { if (!param.isObject()) return null; if (param.has(propname)) return null; else return Json.array().add(Json.make("Required property " + propname + " missing from object " + param.toString(maxchars))); } } class CheckObject implements Instruction { int min = 0, max = Integer.MAX_VALUE; Instruction additionalSchema = any; ArrayList props = new ArrayList(); ArrayList patternProps = new ArrayList(); // Object validation class CheckProperty implements Instruction { String name; Instruction schema; public CheckProperty(String name, Instruction schema) { this.name = name; this.schema = schema; } public Json apply(Json param) { Json value = param.at(name); if (value == null) return null; else return schema.apply(param.at(name)); } } class CheckPatternProperty // implements Instruction { Pattern pattern; Instruction schema; public CheckPatternProperty(String pattern, Instruction schema) { this.pattern = Pattern.compile(pattern); this.schema = schema; } public Json apply(Json param, Set found) { Json errors = null; for (Map.Entry e : param.asJsonMap().entrySet()) if (pattern.matcher(e.getKey()).find()) { found.add(e.getKey()); errors = maybeError(errors, schema.apply(e.getValue())); } return errors; } } public Json apply(Json param) { Json errors = null; if (!param.isObject()) return errors; HashSet checked = new HashSet(); for (CheckProperty I : props) { if (param.has(I.name)) checked.add(I.name); errors = maybeError(errors, I.apply(param)); } for (CheckPatternProperty I : patternProps) { errors = maybeError(errors, I.apply(param, checked)); } if (additionalSchema != any) for (Map.Entry e : param.asJsonMap().entrySet()) if (!checked.contains(e.getKey())) errors = maybeError(errors, additionalSchema == null ? Json.make("Extra property '" + e.getKey() + "', schema doesn't allow any properties not explicitly defined:" + param.toString(maxchars)) : additionalSchema.apply(e.getValue())); if (param.asJsonMap().size() < min) errors = maybeError(errors, Json.make("Object " + param.toString(maxchars) + " has fewer than the permitted " + min + " number of properties.")); if (param.asJsonMap().size() > max) errors = maybeError(errors, Json.make("Object " + param.toString(maxchars) + " has more than the permitted " + min + " number of properties.")); return errors; } } class Sequence implements Instruction { ArrayList seq = new ArrayList(); public Json apply(Json param) { Json errors = null; for (Instruction I : seq) errors = maybeError(errors, I.apply(param)); return errors; } public Sequence add(Instruction I) { seq.add(I); return this; } } class CheckType implements Instruction { Json types; public CheckType(Json types) { this.types = types; } public Json apply(Json param) { String ptype = param.isString() ? "string" : param.isObject() ? "object" : param.isArray() ? "array" : param.isNumber() ? "number" : param.isNull() ? "null" : "boolean"; for (Json type : types.asJsonList()) if (type.asString().equals(ptype)) return null; else if (type.asString().equals("integer") && param.isNumber() && param.asDouble() % 1 == 0) return null; return Json.array().add(Json.make("Type mistmatch for " + param.toString(maxchars) + ", allowed types: " + types)); } } class CheckEnum implements Instruction { Json theenum; public CheckEnum(Json theenum) { this.theenum = theenum; } public Json apply(Json param) { for (Json option : theenum.asJsonList()) if (param.equals(option)) return null; return Json.array().add("Element " + param.toString(maxchars) + " doesn't match any of enumerated possibilities " + theenum); } } class CheckAny implements Instruction { ArrayList alternates = new ArrayList(); Json schema; public Json apply(Json param) { for (Instruction I : alternates) if (I.apply(param) == null) return null; return Json.array().add("Element " + param.toString(maxchars) + " must conform to at least one of available sub-schemas " + schema.toString(maxchars)); } } class CheckOne implements Instruction { ArrayList alternates = new ArrayList(); Json schema; public Json apply(Json param) { int matches = 0; Json errors = Json.array(); for (Instruction I : alternates) { Json result = I.apply(param); if (result == null) matches++; else errors.add(result); } if (matches != 1) { return Json.array().add("Element " + param.toString(maxchars) + " must conform to exactly one of available sub-schemas, but not more " + schema.toString(maxchars)).add(errors); } else return null; } } class CheckNot implements Instruction { Instruction I; Json schema; public CheckNot(Instruction I, Json schema) { this.I = I; this.schema = schema; } public Json apply(Json param) { if (I.apply(param) != null) return null; else return Json.array().add("Element " + param.toString(maxchars) + " must NOT conform to the schema " + schema.toString(maxchars)); } } class CheckSchemaDependency implements Instruction { Instruction schema; String property; public CheckSchemaDependency(String property, Instruction schema) { this.property = property; this.schema = schema; } public Json apply(Json param) { if (!param.isObject()) return null; else if (!param.has(property)) return null; else return (schema.apply(param)); } } class CheckPropertyDependency implements Instruction { Json required; String property; public CheckPropertyDependency(String property, Json required) { this.property = property; this.required = required; } public Json apply(Json param) { if (!param.isObject()) return null; if (!param.has(property)) return null; else { Json errors = null; for (Json p : required.asJsonList()) if (!param.has(p.asString())) errors = maybeError(errors, Json.make("Conditionally required property " + p + " missing from object " + param.toString(maxchars))); return errors; } } } Instruction compile(Json S, Map compiled) { Instruction result = compiled.get(S); if (result != null) return result; Sequence seq = new Sequence(); compiled.put(S, seq); if (S.has("type") && !S.is("type", "any")) seq.add(new CheckType(S.at("type").isString() ? Json.array().add(S.at("type")) : S.at("type"))); if (S.has("enum")) seq.add(new CheckEnum(S.at("enum"))); if (S.has("allOf")) { Sequence sub = new Sequence(); for (Json x : S.at("allOf").asJsonList()) sub.add(compile(x, compiled)); seq.add(sub); } if (S.has("anyOf")) { CheckAny any = new CheckAny(); any.schema = S.at("anyOf"); for (Json x : any.schema.asJsonList()) any.alternates.add(compile(x, compiled)); seq.add(any); } if (S.has("oneOf")) { CheckOne any = new CheckOne(); any.schema = S.at("oneOf"); for (Json x : any.schema.asJsonList()) any.alternates.add(compile(x, compiled)); seq.add(any); } if (S.has("not")) seq.add(new CheckNot(compile(S.at("not"), compiled), S.at("not"))); if (S.has("required") && S.at("required").isArray()) { for (Json p : S.at("required").asJsonList()) seq.add(new CheckPropertyPresent(p.asString())); } CheckObject objectCheck = new CheckObject(); if (S.has("properties")) for (Map.Entry p : S.at("properties").asJsonMap().entrySet()) objectCheck.props.add(objectCheck.new CheckProperty( p.getKey(), compile(p.getValue(), compiled))); if (S.has("patternProperties")) for (Map.Entry p : S.at("patternProperties").asJsonMap().entrySet()) objectCheck.patternProps.add(objectCheck.new CheckPatternProperty(p.getKey(), compile(p.getValue(), compiled))); if (S.has("additionalProperties")) { if (S.at("additionalProperties").isObject()) objectCheck.additionalSchema = compile(S.at("additionalProperties"), compiled); else if (!S.at("additionalProperties").asBoolean()) objectCheck.additionalSchema = null; // means no additional properties allowed } if (S.has("minProperties")) objectCheck.min = S.at("minProperties").asInteger(); if (S.has("maxProperties")) objectCheck.max = S.at("maxProperties").asInteger(); if (!objectCheck.props.isEmpty() || !objectCheck.patternProps.isEmpty() || objectCheck.additionalSchema != any || objectCheck.min > 0 || objectCheck.max < Integer.MAX_VALUE) seq.add(objectCheck); CheckArray arrayCheck = new CheckArray(); if (S.has("items")) if (S.at("items").isObject()) arrayCheck.schema = compile(S.at("items"), compiled); else { arrayCheck.schemas = new ArrayList(); for (Json s : S.at("items").asJsonList()) arrayCheck.schemas.add(compile(s, compiled)); } if (S.has("additionalItems")) if (S.at("additionalItems").isObject()) arrayCheck.additionalSchema = compile(S.at("additionalItems"), compiled); else if (!S.at("additionalItems").asBoolean()) arrayCheck.additionalSchema = null; if (S.has("uniqueItems")) arrayCheck.uniqueitems = S.at("uniqueItems").asBoolean(); if (S.has("minItems")) arrayCheck.min = S.at("minItems").asInteger(); if (S.has("maxItems")) arrayCheck.max = S.at("maxItems").asInteger(); if (arrayCheck.schema != null || arrayCheck.schemas != null || arrayCheck.additionalSchema != any || arrayCheck.uniqueitems != null || arrayCheck.max < Integer.MAX_VALUE || arrayCheck.min > 0) seq.add(arrayCheck); CheckNumber numberCheck = new CheckNumber(); if (S.has("minimum")) numberCheck.min = S.at("minimum").asDouble(); if (S.has("maximum")) numberCheck.max = S.at("maximum").asDouble(); if (S.has("multipleOf")) numberCheck.multipleOf = S.at("multipleOf").asDouble(); if (S.has("exclusiveMinimum")) numberCheck.exclusiveMin = S.at("exclusiveMinimum").asBoolean(); if (S.has("exclusiveMaximum")) numberCheck.exclusiveMax = S.at("exclusiveMaximum").asBoolean(); if (!Double.isNaN(numberCheck.min) || !Double.isNaN(numberCheck.max) || !Double.isNaN(numberCheck.multipleOf)) seq.add(numberCheck); CheckString stringCheck = new CheckString(); if (S.has("minLength")) stringCheck.min = S.at("minLength").asInteger(); if (S.has("maxLength")) stringCheck.max = S.at("maxLength").asInteger(); if (S.has("pattern")) stringCheck.pattern = Pattern.compile(S.at("pattern").asString()); if (stringCheck.min > 0 || stringCheck.max < Integer.MAX_VALUE || stringCheck.pattern != null) seq.add(stringCheck); if (S.has("dependencies")) for (Map.Entry e : S.at("dependencies").asJsonMap().entrySet()) if (e.getValue().isObject()) seq.add(new CheckSchemaDependency(e.getKey(), compile(e.getValue(), compiled))); else if (e.getValue().isArray()) seq.add(new CheckPropertyDependency(e.getKey(), e.getValue())); else seq.add(new CheckPropertyDependency(e.getKey(), Json.array(e.getValue()))); result = seq.seq.size() == 1 ? seq.seq.get(0) : seq; compiled.put(S, result); return result; } int maxchars = 50; URI uri; Json theschema; Instruction start; DefaultSchema(URI uri, Json theschema, Function relativeReferenceResolver) { try { this.uri = uri == null ? new URI("") : uri; if (relativeReferenceResolver == null) relativeReferenceResolver = new Function() { public Json apply(URI docuri) { try { return Json.read(fetchContent(docuri.toURL())); } catch(Exception ex) { throw new RuntimeException(ex); } }}; this.theschema = theschema.dup(); this.theschema = expandReferences(this.theschema, this.theschema, this.uri, new HashMap(), new IdentityHashMap(), relativeReferenceResolver); } catch (Exception ex) { throw new RuntimeException(ex); } this.start = compile(this.theschema, new IdentityHashMap()); } public Json validate(Json document) { Json result = Json.object("ok", true); Json errors = start.apply(document); return errors == null ? result : result.set("errors", errors).set("ok", false); } public Json toJson() { return theschema; } public Json generate(Json options) { // TODO... return Json.nil(); } } public static Schema schema(Json S) { return new DefaultSchema(null, S, null); } public static Schema schema(URI uri) { return schema(uri, null); } public static Schema schema(URI uri, Function relativeReferenceResolver) { try { return new DefaultSchema(uri, Json.read(Json.fetchContent(uri.toURL())), relativeReferenceResolver); } catch (Exception ex) { throw new RuntimeException(ex); } } public static Schema schema(Json S, URI uri) { return new DefaultSchema(uri, S, null); } public static class DefaultFactory implements Factory { public Json nil() { return Json.topnull; } public Json bool(boolean x) { return new BooleanJson(x ? Boolean.TRUE : Boolean.FALSE, null); } public Json string(String x) { return new StringJson(x, null); } public Json number(Number x) { return new NumberJson(x, null); } public Json array() { return new ArrayJson(); } public Json object() { return new ObjectJson(); } public Json make(Object anything) { if (anything == null) return topnull; else if (anything instanceof Json) return (Json)anything; else if (anything instanceof String) return factory().string((String)anything); else if (anything instanceof Collection) { Json L = array(); for (Object x : (Collection)anything) L.add(factory().make(x)); return L; } else if (anything instanceof Map) { Json O = object(); for (Map.Entry x : ((Map)anything).entrySet()) O.set(x.getKey().toString(), factory().make(x.getValue())); return O; } else if (anything instanceof Boolean) return factory().bool((Boolean)anything); else if (anything instanceof Number) return factory().number((Number)anything); else if (anything.getClass().isArray()) { Class comp = anything.getClass().getComponentType(); if (!comp.isPrimitive()) return Json.array((Object[])anything); Json A = array(); if (boolean.class == comp) for (boolean b : (boolean[])anything) A.add(b); else if (byte.class == comp) for (byte b : (byte[])anything) A.add(b); else if (char.class == comp) for (char b : (char[])anything) A.add(b); else if (short.class == comp) for (short b : (short[])anything) A.add(b); else if (int.class == comp) for (int b : (int[])anything) A.add(b); else if (long.class == comp) for (long b : (long[])anything) A.add(b); else if (float.class == comp) for (float b : (float[])anything) A.add(b); else if (double.class == comp) for (double b : (double[])anything) A.add(b); return A; } else throw new IllegalArgumentException("Don't know how to convert to Json : " + anything); } } public static final Factory defaultFactory = new DefaultFactory(); private static Factory globalFactory = defaultFactory; // TODO: maybe use initialValue thread-local method to attach global factory by default here... private static ThreadLocal threadFactory = new ThreadLocal(); /** *

Return the {@link Factory} currently in effect. This is the factory that the {@link #make(Object)} method * will dispatch on upon determining the type of its argument. If you already know the type * of element to construct, you can avoid the type introspection implicit to the make method * and call the factory directly. This will result in an optimization.

* * @return the factory */ public static Factory factory() { Factory f = threadFactory.get(); return f != null ? f : globalFactory; } /** *

* Specify a global Json {@link Factory} to be used by all threads that don't have a * specific thread-local factory attached to them. *

* * @param factory The new global factory */ public static void setGlobalFactory(Factory factory) { globalFactory = factory; } /** *

* Attach a thread-local Json {@link Factory} to be used specifically by this thread. Thread-local * Json factories are the only means to have different {@link Factory} implementations used simultaneously * in the same application (well, more accurately, the same ClassLoader). *

* * @param factory the new thread local factory */ public static void attachFactory(Factory factory) { threadFactory.set(factory); } /** *

* Clear the thread-local factory previously attached to this thread via the * {@link #attachFactory(Factory)} method. The global factory takes effect after * a call to this method. *

*/ public static void detachFactory() { threadFactory.remove(); } /** *

* Parse a JSON entity from its string representation. *

* * @param jsonAsString A valid JSON representation as per the json.org * grammar. Cannot be null. * @return The JSON entity parsed: an object, array, string, number or boolean, or null. Note that * this method will never return the actual Java null. */ public static Json read(String jsonAsString) { return (Json)new Reader().read(jsonAsString); } /** *

* Parse a JSON entity from a URL. *

* * @param location A valid URL where to load a JSON document from. Cannot be null. * @return The JSON entity parsed: an object, array, string, number or boolean, or null. Note that * this method will never return the actual Java null. */ public static Json read(URL location) { return (Json)new Reader().read(fetchContent(location)); } /** *

* Parse a JSON entity from a {@link CharacterIterator}. *

* @param it A character iterator. * @return the parsed JSON element * @see #read(String) */ public static Json read(CharacterIterator it) { return (Json)new Reader().read(it); } /** * @return the null Json instance. */ public static Json nil() { return factory().nil(); } /** * @return a newly constructed, empty JSON object. */ public static Json object() { return factory().object(); } /** *

Return a new JSON object initialized from the passed list of * name/value pairs. The number of arguments must * be even. Each argument at an even position is taken to be a name * for the following value. The name arguments are normally of type * Java String, but they can be of any other type having an appropriate * toString method. Each value is first converted * to a Json instance using the {@link #make(Object)} method. *

* @param args A sequence of name value pairs. * @return the new JSON object. */ public static Json object(Object...args) { Json j = object(); if (args.length % 2 != 0) throw new IllegalArgumentException("An even number of arguments is expected."); for (int i = 0; i < args.length; i++) j.set(args[i].toString(), factory().make(args[++i])); return j; } /** * @return a new constructed, empty JSON array. */ public static Json array() { return factory().array(); } /** *

Return a new JSON array filled up with the list of arguments.

* * @param args The initial content of the array. * @return the new JSON array */ public static Json array(Object...args) { Json A = array(); for (Object x : args) A.add(factory().make(x)); return A; } /** *

* Exposes some internal methods that are useful for {@link org.sharegov.mjson.Json.Factory} implementations * or other extension/layers of the library. *

* * @author Borislav Iordanov * */ public static class help { /** *

* Perform JSON escaping so that ", <, >, etc. characters are properly encoded in the * JSON string representation before returning to the client code. This is useful when * serializing property names or string values. *

*/ public static String escape(String string) { return escaper.escapeJsonString(string); } /** *

* Given a JSON Pointer, as per RFC 6901, return the nested JSON value within * the element parameter. *

*/ public static Json resolvePointer(String pointer, Json element) { return Json.resolvePointer(pointer, element); } } /** *

* Convert an arbitrary Java instance to a {@link Json} instance. *

* *

* Maps, Collections and arrays are recursively copied where each of * their elements concerted into Json instances as well. The keys * of a {@link Map} parameter are normally strings, but anything with a meaningful * toString implementation will work as well. *

* * @param anything Any Java object that the current JSON factory in effect is capable of handling. * @return The Json. This method will never return null. It will * throw an {@link IllegalArgumentException} if it doesn't know how to convert the argument * to a Json instance. * @throws IllegalArgumentException when the concrete type of the parameter is * unknown. */ public static Json make(Object anything) { return factory().make(anything); } // end of static utility method section Json enclosing = null; protected Json() { } protected Json(Json enclosing) { this.enclosing = enclosing; } /** *

Return a string representation of this that does * not exceed a certain maximum length. This is useful in constructing * error messages or any other place where only a "preview" of the * JSON element should be displayed. Some JSON structures can get * very large and this method will help avoid string serializing * the whole of them.

* @param maxCharacters The maximum number of characters for * the string representation. * @return The string representation of this object. */ public String toString(int maxCharacters) { return toString(); } /** *

Explicitly set the parent of this element. The parent is presumably an array * or an object. Normally, there's no need to call this method as the parent is * automatically set by the framework. You may need to call it however, if you implement * your own {@link Factory} with your own implementations of the Json types. *

* * @param enclosing The parent element. */ public void attachTo(Json enclosing) { this.enclosing = enclosing; } /** * @return the Json entity, if any, enclosing this * Json. The returned value can be null or * a Json object or list, but not one of the primitive types. */ public final Json up() { return enclosing; } /** * @return a clone (a duplicate) of this Json entity. Note that cloning * is deep if array and objects. Primitives are also cloned, even though their values are immutable * because the new enclosing entity (the result of the {@link #up()} method) may be different. * since they are immutable. */ public Json dup() { return this; } /** *

Return the Json element at the specified index of this * Json array. This method applies only to Json arrays. *

* * @param index The index of the desired element. * @return The JSON element at the specified index in this array. */ public Json at(int index) { throw new UnsupportedOperationException(); } /** *

* Return the specified property of a Json object or null * if there's no such property. This method applies only to Json objects. *

* @param The property name. * @return The JSON element that is the value of that property. */ public Json at(String property) { throw new UnsupportedOperationException(); } /** *

* Return the specified property of a Json object if it exists. * If it doesn't, then create a new property with value the def * parameter and return that parameter. *

* * @param property The property to return. * @param def The default value to set and return in case the property doesn't exist. */ public final Json at(String property, Json def) { Json x = at(property); if (x == null) { // set(property, def); return def; } else return x; } /** *

* Return the specified property of a Json object if it exists. * If it doesn't, then create a new property with value the def * parameter and return that parameter. *

* * @param property The property to return. * @param def The default value to set and return in case the property doesn't exist. */ public final Json at(String property, Object def) { return at(property, make(def)); } /** *

* Return true if this Json object has the specified property * and false otherwise. *

* * @param property The name of the property. */ public boolean has(String property) { throw new UnsupportedOperationException(); } /** *

* Return true if and only if this Json object has a property with * the specified value. In particular, if the object has no such property false is returned. *

* * @param property The property name. * @param value The value to compare with. Comparison is done via the equals method. * If the value is not an instance of Json, it is first converted to * such an instance. * @return */ public boolean is(String property, Object value) { throw new UnsupportedOperationException(); } /** *

* Return true if and only if this Json array has an element with * the specified value at the specified index. In particular, if the array has no element at * this index, false is returned. *

* * @param index The 0-based index of the element in a JSON array. * @param value The value to compare with. Comparison is done via the equals method. * If the value is not an instance of Json, it is first converted to * such an instance. * @return */ public boolean is(int index, Object value) { throw new UnsupportedOperationException(); } /** *

* Add the specified Json element to this array. *

* * @return this */ public Json add(Json el) { throw new UnsupportedOperationException(); } /** *

* Add an arbitrary Java object to this Json array. The object * is first converted to a Json instance by calling the static * {@link #make} method. *

* * @param anything Any Java object that can be converted to a Json instance. * @return this */ public final Json add(Object anything) { return add(make(anything)); } /** *

* Remove the specified property from a Json object and return * that property. *

* * @param property The property to be removed. * @return The property value or null if the object didn't have such * a property to begin with. */ public Json atDel(String property) { throw new UnsupportedOperationException(); } /** *

* Remove the element at the specified index from a Json array and return * that element. *

* * @param index The index of the element to delete. * @return The element value. */ public Json atDel(int index) { throw new UnsupportedOperationException(); } /** *

* Delete the specified property from a Json object. *

* * @param property The property to be removed. * @return this */ public Json delAt(String property) { throw new UnsupportedOperationException(); } /** *

* Remove the element at the specified index from a Json array. *

* * @param index The index of the element to delete. * @return this */ public Json delAt(int index) { throw new UnsupportedOperationException(); } /** *

* Remove the specified element from a Json array. *

* * @param el The element to delete. * @return this */ public Json remove(Json el) { throw new UnsupportedOperationException(); } /** *

* Remove the specified Java object (converted to a Json instance) * from a Json array. This is equivalent to * remove({@link #make(Object)}). *

* * @param anything The object to delete. * @return this */ public final Json remove(Object anything) { return remove(make(anything)); } /** *

* Set a Json objects's property. *

* * @param property The property name. * @param value The value of the property. * @return this */ public Json set(String property, Json value) { throw new UnsupportedOperationException(); } /** *

* Set a Json objects's property. *

* * @param property The property name. * @param value The value of the property, converted to a Json representation * with {@link #make}. * @return this */ public final Json set(String property, Object value) { return set(property, make(value)); } /** *

* Change the value of a JSON array element. This must be an array. *

* @param index 0-based index of the element in the array. * @param value the new value of the element * @return this */ public Json set(int index, Object value) { throw new UnsupportedOperationException(); } /** *

* Combine this object or array with the passed in object or array. The types of * this and the object argument must match. If both are * Json objects, all properties of the parameter are added to this. * If both are arrays, all elements of the parameter are appended to this *

* @param object The object or array whose properties or elements must be added to this * Json object or array. * @param options A sequence of options that governs the merging process. * @return this */ public Json with(Json object, Json[]options) { throw new UnsupportedOperationException(); } /** * Same as {}@link #with(Json,Json...options)} with each option * argument converted to Json first. */ public Json with(Json object, Object...options) { Json [] jopts = new Json[options.length]; for (int i = 0; i < jopts.length; i++) jopts[i] = make(options[i]); return with(object, jopts); } /** * @return the underlying value of this Json entity. The actual value will * be a Java Boolean, String, Number, Map, List or null. For complex entities (objects * or arrays), the method will perform a deep copy and extra underlying values recursively * for all nested elements. */ public Object getValue() { throw new UnsupportedOperationException(); } /** * @return the boolean value of a boolean Json instance. Call * {@link #isBoolean()} first if you're not sure this instance is indeed a * boolean. */ public boolean asBoolean() { throw new UnsupportedOperationException(); } /** * @return the string value of a string Json instance. Call * {@link #isString()} first if you're not sure this instance is indeed a * string. */ public String asString() { throw new UnsupportedOperationException(); } /** * @return the integer value of a number Json instance. Call * {@link #isNumber()} first if you're not sure this instance is indeed a * number. */ public int asInteger() { throw new UnsupportedOperationException(); } /** * @return the float value of a float Json instance. Call * {@link #isNumber()} first if you're not sure this instance is indeed a * number. */ public float asFloat() { throw new UnsupportedOperationException(); } /** * @return the double value of a number Json instance. Call * {@link #isNumber()} first if you're not sure this instance is indeed a * number. */ public double asDouble() { throw new UnsupportedOperationException(); } /** * @return the long value of a number Json instance. Call * {@link #isNumber()} first if you're not sure this instance is indeed a * number. */ public long asLong() { throw new UnsupportedOperationException(); } /** * @return the short value of a number Json instance. Call * {@link #isNumber()} first if you're not sure this instance is indeed a * number. */ public short asShort() { throw new UnsupportedOperationException(); } /** * @return the byte value of a number Json instance. Call * {@link #isNumber()} first if you're not sure this instance is indeed a * number. */ public byte asByte() { throw new UnsupportedOperationException(); } /** * @return the first character of a string Json instance. Call * {@link #isString()} first if you're not sure this instance is indeed a * string. */ public char asChar() { throw new UnsupportedOperationException(); } /** * @return a map of the properties of an object Json instance. The map * is a clone of the object and can be modified safely without affecting it. Call * {@link #isObject()} first if you're not sure this instance is indeed a * Json object. */ public Map asMap() { throw new UnsupportedOperationException(); } /** * @return the underlying map of properties of a Json object. The returned * map is the actual object representation so any modifications to it are modifications * of the Json object itself. Call * {@link #isObject()} first if you're not sure this instance is indeed a * Json object. */ public Map asJsonMap() { throw new UnsupportedOperationException(); } /** * @return a list of the elements of a Json array. The list is a clone * of the array and can be modified safely without affecting it. Call * {@link #isArray()} first if you're not sure this instance is indeed a * Json array. */ public List asList() { throw new UnsupportedOperationException(); } /** * @return the underlying {@link List} representation of a Json array. * The returned list is the actual array representation so any modifications to it * are modifications of the Json array itself. Call * {@link #isArray()} first if you're not sure this instance is indeed a * Json array. */ public List asJsonList() { throw new UnsupportedOperationException(); } /** * @return true if this is a Json null entity * and false otherwise. */ public boolean isNull() { return false; } /** * @return true if this is a Json string entity * and false otherwise. */ public boolean isString() { return false; } /** * @return true if this is a Json number entity * and false otherwise. */ public boolean isNumber() { return false; } /** * @return true if this is a Json boolean entity * and false otherwise. */ public boolean isBoolean() { return false; } /** * @return true if this is a Json array (i.e. list) entity * and false otherwise. */ public boolean isArray() { return false; } /** * @return true if this is a Json object entity * and false otherwise. */ public boolean isObject(){ return false; } /** * @return true if this is a Json primitive entity * (one of string, number or boolean) and false otherwise. * */ public boolean isPrimitive() { return isString() || isNumber() || isBoolean(); } /** *

* Json-pad this object as an argument to a callback function. *

* * @param callback The name of the callback function. Can be null or empty, * in which case no padding is done. * @return The jsonpadded, stringified version of this object if the callback * is not null or empty, or just the stringified version of the object. */ public String pad(String callback) { return (callback != null && callback.length() > 0) ? callback + "(" + toString() + ");" : toString(); } //------------------------------------------------------------------------- // END OF PUBLIC INTERFACE //------------------------------------------------------------------------- /** * Return an object representing the complete configuration * of a merge. The properties of the object represent paths * of the JSON structure being merged and the values represent * the set of options that apply to each path. * @param options the configuration options * @return the configuration object */ protected Json collectWithOptions(Json...options) { Json result = object(); for (Json opt : options) { if (opt.isString()) { if (!result.has("")) result.set("", object()); result.at("").set(opt.asString(), true); } else { if (!opt.has("for")) opt.set("for", array("")); Json forPaths = opt.at("for"); if (!forPaths.isArray()) forPaths = array(forPaths); for (Json path : forPaths.asJsonList()) { if (!result.has(path.asString())) result.set(path.asString(), object()); Json at_path = result.at(path.asString()); at_path.set("merge", opt.is("merge", true)); at_path.set("dup", opt.is("dup", true)); at_path.set("sort", opt.is("sort", true)); at_path.set("compareBy", opt.at("compareBy", nil())); } } } return result; } static class NullJson extends Json { private static final long serialVersionUID = 1L; NullJson() {} NullJson(Json e) {super(e);} public Object getValue() { return null; } public Json dup() { return new NullJson(); } public boolean isNull() { return true; } public String toString() { return "null"; } public List asList() { return (List)Collections.singletonList(null); } public int hashCode() { return 0; } public boolean equals(Object x) { return x instanceof NullJson; } } static NullJson topnull = new NullJson(); /** *

* Set the parent (i.e. enclosing element) of Json element. *

* * @param el * @param parent */ static void setParent(Json el, Json parent) { if (el.enclosing == null) el.enclosing = parent; else if (el.enclosing instanceof ParentArrayJson) ((ParentArrayJson)el.enclosing).L.add(parent); else { ParentArrayJson A = new ParentArrayJson(); A.L.add(el.enclosing); A.L.add(parent); el.enclosing = A; } } /** *

* Remove/unset the parent (i.e. enclosing element) of Json element. *

* * @param el * @param parent */ static void removeParent(Json el, Json parent) { if (el.enclosing == parent) el.enclosing = null; else if (el.enclosing.isArray()) { ArrayJson A = (ArrayJson)el.enclosing; int idx = 0; while (A.L.get(idx) != parent && idx < A.L.size()) idx++; if (idx < A.L.size()) A.L.remove(idx); } } static class BooleanJson extends Json { private static final long serialVersionUID = 1L; boolean val; BooleanJson() {} BooleanJson(Json e) {super(e);} BooleanJson(Boolean val, Json e) { super(e); this.val = val; } public Object getValue() { return val; } public Json dup() { return new BooleanJson(val, null); } public boolean asBoolean() { return val; } public boolean isBoolean() { return true; } public String toString() { return val ? "true" : "false"; } @SuppressWarnings("unchecked") public List asList() { return (List)(List)Collections.singletonList(val); } public int hashCode() { return val ? 1 : 0; } public boolean equals(Object x) { return x instanceof BooleanJson && ((BooleanJson)x).val == val; } } static class StringJson extends Json { private static final long serialVersionUID = 1L; String val; StringJson() {} StringJson(Json e) {super(e);} StringJson(String val, Json e) { super(e); this.val = val; } public Json dup() { return new StringJson(val, null); } public boolean isString() { return true; } public Object getValue() { return val; } public String asString() { return val; } public int asInteger() { return Integer.parseInt(val); } public float asFloat() { return Float.parseFloat(val); } public double asDouble() { return Double.parseDouble(val); } public long asLong() { return Long.parseLong(val); } public short asShort() { return Short.parseShort(val); } public byte asByte() { return Byte.parseByte(val); } public char asChar() { return val.charAt(0); } @SuppressWarnings("unchecked") public List asList() { return (List)(List)Collections.singletonList(val); } public String toString() { return '"' + escaper.escapeJsonString(val) + '"'; } public String toString(int maxCharacters) { if (val.length() <= maxCharacters) return toString(); else return '"' + escaper.escapeJsonString(val.subSequence(0, maxCharacters)) + "...\""; } public int hashCode() { return val.hashCode(); } public boolean equals(Object x) { return x instanceof StringJson && ((StringJson)x).val.equals(val); } } static class NumberJson extends Json { private static final long serialVersionUID = 1L; Number val; NumberJson() {} NumberJson(Json e) {super(e);} NumberJson(Number val, Json e) { super(e); this.val = val; } public Json dup() { return new NumberJson(val, null); } public boolean isNumber() { return true; } public Object getValue() { return val; } public String asString() { return val.toString(); } public int asInteger() { return val.intValue(); } public float asFloat() { return val.floatValue(); } public double asDouble() { return val.doubleValue(); } public long asLong() { return val.longValue(); } public short asShort() { return val.shortValue(); } public byte asByte() { return val.byteValue(); } @SuppressWarnings("unchecked") public List asList() { return (List)(List)Collections.singletonList(val); } public String toString() { return val.toString(); } public int hashCode() { return val.hashCode(); } public boolean equals(Object x) { return x instanceof NumberJson && val.doubleValue() == ((NumberJson)x).val.doubleValue(); } } static class ArrayJson extends Json { private static final long serialVersionUID = 1L; List L = new ArrayList(); ArrayJson() { } ArrayJson(Json e) { super(e); } public Json dup() { ArrayJson j = new ArrayJson(); for (Json e : L) { Json v = e.dup(); v.enclosing = j; j.L.add(v); } return j; } public Json set(int index, Object value) { Json jvalue = make(value); L.set(index, jvalue); setParent(jvalue, this); return this; } public List asJsonList() { return L; } public List asList() { ArrayList A = new ArrayList(); for (Json x: L) A.add(x.getValue()); return A; } public boolean is(int index, Object value) { if (index < 0 || index >= L.size()) return false; else return L.get(index).equals(make(value)); } public Object getValue() { return asList(); } public boolean isArray() { return true; } public Json at(int index) { return L.get(index); } public Json add(Json el) { L.add(el); setParent(el, this); return this; } public Json remove(Json el) { L.remove(el); el.enclosing = null; return this; } boolean isEqualJson(Json left, Json right) { if (left == null) return right == null; else return left.equals(right); } boolean isEqualJson(Json left, Json right, Json fields) { if (fields.isNull()) return left.equals(right); else if (fields.isString()) return isEqualJson(resolvePointer(fields.asString(), left), resolvePointer(fields.asString(), right)); else if (fields.isArray()) { for (Json field : fields.asJsonList()) if (!isEqualJson(resolvePointer(field.asString(), left), resolvePointer(field.asString(), right))) return false; return true; } else throw new IllegalArgumentException("Compare by options should be either a property name or an array of property names: " + fields); } @SuppressWarnings({ "unchecked", "rawtypes" }) int compareJson(Json left, Json right, Json fields) { if (fields.isNull()) return ((Comparable)left.getValue()).compareTo(right.getValue()); else if (fields.isString()) { Json leftProperty = resolvePointer(fields.asString(), left); Json rightProperty = resolvePointer(fields.asString(), right); return ((Comparable)leftProperty).compareTo(rightProperty); } else if (fields.isArray()) { for (Json field : fields.asJsonList()) { Json leftProperty = resolvePointer(field.asString(), left); Json rightProperty = resolvePointer(field.asString(), right); int result = ((Comparable) leftProperty).compareTo(rightProperty); if (result != 0) return result; } return 0; } else throw new IllegalArgumentException("Compare by options should be either a property name or an array of property names: " + fields); } Json withOptions(Json array, Json allOptions, String path) { Json opts = allOptions.at(path, object()); boolean dup = opts.is("dup", true); Json compareBy = opts.at("compareBy", nil()); if (opts.is("sort", true)) { int thisIndex = 0, thatIndex = 0; while (thatIndex < array.asJsonList().size()) { Json thatElement = array.at(thatIndex); if (thisIndex == L.size()) { L.add(dup ? thatElement.dup() : thatElement); thisIndex++; thatIndex++; continue; } int compared = compareJson(at(thisIndex), thatElement, compareBy); if (compared < 0) // this < that thisIndex++; else if (compared > 0) // this > that { L.add(thisIndex, dup ? thatElement.dup() : thatElement); thatIndex++; } else { // equal, ignore thatIndex++; } } } else { for (Json thatElement : array.asJsonList()) { boolean present = false; for (Json thisElement : L) if (isEqualJson(thisElement, thatElement, compareBy)) { present = true; break; } if (!present) L.add(dup ? thatElement.dup() : thatElement); } } return this; } public Json with(Json object, Json...options) { if (object == null) return this; if (!object.isArray()) add(object); else if (options.length > 0) { Json O = collectWithOptions(options); return withOptions(object, O, ""); } else // what about "enclosing" here? we don't have a provision where a Json // element belongs to more than one enclosing elements... L.addAll(((ArrayJson)object).L); return this; } public Json atDel(int index) { Json el = L.remove(index); if (el != null) el.enclosing = null; return el; } public Json delAt(int index) { Json el = L.remove(index); if (el != null) el.enclosing = null; return this; } public String toString() { return toString(Integer.MAX_VALUE); } public String toString(int maxCharacters) { return toStringImpl(maxCharacters, new IdentityHashMap()); } String toStringImpl(int maxCharacters, Map done) { StringBuilder sb = new StringBuilder("["); for (Iterator i = L.iterator(); i.hasNext(); ) { Json value = i.next(); String s = value.isObject() ? ((ObjectJson)value).toStringImpl(maxCharacters, done) : value.isArray() ? ((ArrayJson)value).toStringImpl(maxCharacters, done) : value.toString(maxCharacters); if (sb.length() + s.length() > maxCharacters) s = s.substring(0, Math.max(0, maxCharacters - sb.length())); else sb.append(s); if (i.hasNext()) sb.append(","); if (sb.length() >= maxCharacters) { sb.append("..."); break; } } sb.append("]"); return sb.toString(); } public int hashCode() { return L.hashCode(); } public boolean equals(Object x) { return x instanceof ArrayJson && ((ArrayJson)x).L.equals(L); } } static class ParentArrayJson extends ArrayJson { /** * */ private static final long serialVersionUID = 1L; } static class ObjectJson extends Json { private static final long serialVersionUID = 1L; Map object = new HashMap(); ObjectJson() { } ObjectJson(Json e) { super(e); } public Json dup() { ObjectJson j = new ObjectJson(); for (Map.Entry e : object.entrySet()) { Json v = e.getValue().dup(); v.enclosing = j; j.object.put(e.getKey(), v); } return j; } public boolean has(String property) { return object.containsKey(property); } public boolean is(String property, Object value) { Json p = object.get(property); if (p == null) return false; else return p.equals(make(value)); } public Json at(String property) { return object.get(property); } protected Json withOptions(Json other, Json allOptions, String path) { if (!allOptions.has(path)) allOptions.set(path, object()); Json options = allOptions.at(path, object()); boolean duplicate = options.is("dup", true); if (options.is("merge", true)) { for (Map.Entry e : other.asJsonMap().entrySet()) { Json local = object.get(e.getKey()); if (local instanceof ObjectJson) ((ObjectJson)local).withOptions(e.getValue(), allOptions, path + "/" + e.getKey()); else if (local instanceof ArrayJson) ((ArrayJson)local).withOptions(e.getValue(), allOptions, path + "/" + e.getKey()); else set(e.getKey(), duplicate ? e.getValue().dup() : e.getValue()); } } else if (duplicate) for (Map.Entry e : other.asJsonMap().entrySet()) set(e.getKey(), e.getValue().dup()); else for (Map.Entry e : other.asJsonMap().entrySet()) set(e.getKey(), e.getValue()); return this; } public Json with(Json x, Json...options) { if (x == null) return this; if (!x.isObject()) throw new UnsupportedOperationException(); if (options.length > 0) { Json O = collectWithOptions(options); return withOptions(x, O, ""); } else for (Map.Entry e : x.asJsonMap().entrySet()) set(e.getKey(), e.getValue()); return this; } public Json set(String property, Json el) { if (property == null) throw new IllegalArgumentException("Null property names are not allowed, value is " + el); if (el == null) el = nil(); setParent(el, this); object.put(property, el); return this; } public Json atDel(String property) { Json el = object.remove(property); removeParent(el, this); return el; } public Json delAt(String property) { Json el = object.remove(property); removeParent(el, this); return this; } public Object getValue() { return asMap(); } public boolean isObject() { return true; } public Map asMap() { HashMap m = new HashMap(); for (Map.Entry e : object.entrySet()) m.put(e.getKey(), e.getValue().getValue()); return m; } @Override public Map asJsonMap() { return object; } public String toString() { return toString(Integer.MAX_VALUE); } public String toString(int maxCharacters) { return toStringImpl(maxCharacters, new IdentityHashMap()); } String toStringImpl(int maxCharacters, Map done) { StringBuilder sb = new StringBuilder("{"); if (done.containsKey(this)) return sb.append("...}").toString(); done.put(this, this); for (Iterator> i = object.entrySet().iterator(); i.hasNext(); ) { Map.Entry x = i.next(); sb.append('"'); sb.append(escaper.escapeJsonString(x.getKey())); sb.append('"'); sb.append(":"); String s = x.getValue().isObject() ? ((ObjectJson)x.getValue()).toStringImpl(maxCharacters, done) : x.getValue().isArray() ? ((ArrayJson)x.getValue()).toStringImpl(maxCharacters, done) : x.getValue().toString(maxCharacters); if (sb.length() + s.length() > maxCharacters) s = s.substring(0, Math.max(0, maxCharacters - sb.length())); sb.append(s); if (i.hasNext()) sb.append(","); if (sb.length() >= maxCharacters) { sb.append("..."); break; } } sb.append("}"); return sb.toString(); } public int hashCode() { return object.hashCode(); } public boolean equals(Object x) { return x instanceof ObjectJson && ((ObjectJson)x).object.equals(object); } } // ------------------------------------------------------------------------ // Extra utilities, taken from around the internet: // ------------------------------------------------------------------------ /* * Copyright (C) 2008 Google Inc. * * 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. */ /** * A utility class that is used to perform JSON escaping so that ", <, >, etc. characters are * properly encoded in the JSON string representation before returning to the client code. * *

This class contains a single method to escape a passed in string value: *

	 *   String jsonStringValue = "beforeQuote\"afterQuote";
	 *   String escapedValue = Escaper.escapeJsonString(jsonStringValue);
	 * 

* * @author Inderjeet Singh * @author Joel Leitch */ static Escaper escaper = new Escaper(false); final static class Escaper { private static final char[] HEX_CHARS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; private static final Set JS_ESCAPE_CHARS; private static final Set HTML_ESCAPE_CHARS; static { Set mandatoryEscapeSet = new HashSet(); mandatoryEscapeSet.add('"'); mandatoryEscapeSet.add('\\'); JS_ESCAPE_CHARS = Collections.unmodifiableSet(mandatoryEscapeSet); Set htmlEscapeSet = new HashSet(); htmlEscapeSet.add('<'); htmlEscapeSet.add('>'); htmlEscapeSet.add('&'); htmlEscapeSet.add('='); htmlEscapeSet.add('\''); // htmlEscapeSet.add('/'); -- Removing slash for now since it causes some incompatibilities HTML_ESCAPE_CHARS = Collections.unmodifiableSet(htmlEscapeSet); } private final boolean escapeHtmlCharacters; Escaper(boolean escapeHtmlCharacters) { this.escapeHtmlCharacters = escapeHtmlCharacters; } public String escapeJsonString(CharSequence plainText) { StringBuilder escapedString = new StringBuilder(plainText.length() + 20); try { escapeJsonString(plainText, escapedString); } catch (IOException e) { throw new RuntimeException(e); } return escapedString.toString(); } private void escapeJsonString(CharSequence plainText, StringBuilder out) throws IOException { int pos = 0; // Index just past the last char in plainText written to out. int len = plainText.length(); for (int charCount, i = 0; i < len; i += charCount) { int codePoint = Character.codePointAt(plainText, i); charCount = Character.charCount(codePoint); if (!isControlCharacter(codePoint) && !mustEscapeCharInJsString(codePoint)) { continue; } out.append(plainText, pos, i); pos = i + charCount; switch (codePoint) { case '\b': out.append("\\b"); break; case '\t': out.append("\\t"); break; case '\n': out.append("\\n"); break; case '\f': out.append("\\f"); break; case '\r': out.append("\\r"); break; case '\\': out.append("\\\\"); break; case '/': out.append("\\/"); break; case '"': out.append("\\\""); break; default: appendHexJavaScriptRepresentation(codePoint, out); break; } } out.append(plainText, pos, len); } private boolean mustEscapeCharInJsString(int codepoint) { if (!Character.isSupplementaryCodePoint(codepoint)) { char c = (char) codepoint; return JS_ESCAPE_CHARS.contains(c) || (escapeHtmlCharacters && HTML_ESCAPE_CHARS.contains(c)); } return false; } private static boolean isControlCharacter(int codePoint) { // JSON spec defines these code points as control characters, so they must be escaped return codePoint < 0x20 || codePoint == 0x2028 // Line separator || codePoint == 0x2029 // Paragraph separator || (codePoint >= 0x7f && codePoint <= 0x9f); } private static void appendHexJavaScriptRepresentation(int codePoint, Appendable out) throws IOException { if (Character.isSupplementaryCodePoint(codePoint)) { // Handle supplementary unicode values which are not representable in // javascript. We deal with these by escaping them as two 4B sequences // so that they will round-trip properly when sent from java to javascript // and back. char[] surrogates = Character.toChars(codePoint); appendHexJavaScriptRepresentation(surrogates[0], out); appendHexJavaScriptRepresentation(surrogates[1], out); return; } out.append("\\u") .append(HEX_CHARS[(codePoint >>> 12) & 0xf]) .append(HEX_CHARS[(codePoint >>> 8) & 0xf]) .append(HEX_CHARS[(codePoint >>> 4) & 0xf]) .append(HEX_CHARS[codePoint & 0xf]); } } public static class MalformedJsonException extends RuntimeException { private static final long serialVersionUID = 1L; public MalformedJsonException(String msg) { super(msg); } } private static class Reader { private static final Object OBJECT_END = new String("}"); private static final Object ARRAY_END = new String("]"); private static final Object OBJECT_START = new String("{"); private static final Object ARRAY_START = new String("["); private static final Object COLON = new String(":"); private static final Object COMMA = new String(","); private static final HashSet PUNCTUATION = new HashSet( Arrays.asList(OBJECT_END, OBJECT_START, ARRAY_END, ARRAY_START, COLON, COMMA)); public static final int FIRST = 0; public static final int CURRENT = 1; public static final int NEXT = 2; private static Map escapes = new HashMap(); static { escapes.put(new Character('"'), new Character('"')); escapes.put(new Character('\\'), new Character('\\')); escapes.put(new Character('/'), new Character('/')); escapes.put(new Character('b'), new Character('\b')); escapes.put(new Character('f'), new Character('\f')); escapes.put(new Character('n'), new Character('\n')); escapes.put(new Character('r'), new Character('\r')); escapes.put(new Character('t'), new Character('\t')); } private CharacterIterator it; private char c; private Object token; private StringBuffer buf = new StringBuffer(); private char next() { if (it.getIndex() == it.getEndIndex()) throw new MalformedJsonException("Reached end of input at the " + it.getIndex() + "th character."); c = it.next(); return c; } private char previous() { c = it.previous(); return c; } private void skipWhiteSpace() { do { if (Character.isWhitespace(c)) ; else if (c == '/') { next(); if (c == '*') { // skip multiline comments while (c != CharacterIterator.DONE) if (next() == '*' && next() == '/') break; if (c == CharacterIterator.DONE) throw new MalformedJsonException("Unterminated comment while parsing JSON string."); } else if (c == '/') while (c != '\n' && c != CharacterIterator.DONE) next(); else { previous(); break; } } else break; } while (next() != CharacterIterator.DONE); } public Object read(CharacterIterator ci, int start) { it = ci; switch (start) { case FIRST: c = it.first(); break; case CURRENT: c = it.current(); break; case NEXT: c = it.next(); break; } return read(); } public Object read(CharacterIterator it) { return read(it, NEXT); } public Object read(String string) { return read(new StringCharacterIterator(string), FIRST); } private void expected(Object expectedToken, Object actual) { if (expectedToken != actual) throw new MalformedJsonException("Expected " + expectedToken + ", but got " + actual + " instead"); } @SuppressWarnings("unchecked") private T read() { skipWhiteSpace(); char ch = c; next(); switch (ch) { case '"': token = readString(); break; case '[': token = readArray(); break; case ']': token = ARRAY_END; break; case ',': token = COMMA; break; case '{': token = readObject(); break; case '}': token = OBJECT_END; break; case ':': token = COLON; break; case 't': if (c != 'r' || next() != 'u' || next() != 'e') throw new MalformedJsonException("Invalid JSON token: expected 'true' keyword."); next(); token = factory().bool(Boolean.TRUE); break; case'f': if (c != 'a' || next() != 'l' || next() != 's' || next() != 'e') throw new MalformedJsonException("Invalid JSON token: expected 'false' keyword."); next(); token = factory().bool(Boolean.FALSE); break; case 'n': if (c != 'u' || next() != 'l' || next() != 'l') throw new MalformedJsonException("Invalid JSON token: expected 'null' keyword."); next(); token = nil(); break; default: c = it.previous(); if (Character.isDigit(c) || c == '-') { token = readNumber(); } else throw new MalformedJsonException("Invalid JSON near position: " + it.getIndex()); } return (T)token; } private String readObjectKey() { Object key = read(); if (key == null) throw new MalformedJsonException("Missing object key (don't forget to put quotes!)."); else if (key == OBJECT_END) return null; else if (PUNCTUATION.contains(key)) throw new MalformedJsonException("Missing object key, found: " + key); else return ((Json)key).asString(); } private Json readObject() { Json ret = object(); String key = readObjectKey(); while (token != OBJECT_END) { expected(COLON, read()); // should be a colon if (token != OBJECT_END) { Json value = read(); ret.set(key, value); if (read() == COMMA) { key = readObjectKey(); if (key == null || PUNCTUATION.contains(key)) throw new MalformedJsonException("Expected a property name, but found: " + key); } else expected(OBJECT_END, token); } } return ret; } private Json readArray() { Json ret = array(); Object value = read(); while (token != ARRAY_END) { if (PUNCTUATION.contains(value)) throw new MalformedJsonException("Expected array element, but found: " + value); ret.add((Json)value); if (read() == COMMA) { value = read(); if (value == ARRAY_END) throw new MalformedJsonException("Expected array element, but found end of array after command."); } else expected(ARRAY_END, token); } return ret; } private Json readNumber() { int length = 0; boolean isFloatingPoint = false; buf.setLength(0); if (c == '-') { add(); } length += addDigits(); if (c == '.') { add(); length += addDigits(); isFloatingPoint = true; } if (c == 'e' || c == 'E') { add(); if (c == '+' || c == '-') { add(); } addDigits(); isFloatingPoint = true; } String s = buf.toString(); Number n = isFloatingPoint ? (length < 17) ? Double.valueOf(s) : new BigDecimal(s) : (length < 20) ? Long.valueOf(s) : new BigInteger(s); return factory().number(n); } private int addDigits() { int ret; for (ret = 0; Character.isDigit(c); ++ret) { add(); } return ret; } private Json readString() { buf.setLength(0); while (c != '"') { if (c == '\\') { next(); if (c == 'u') { add(unicode()); } else { Object value = escapes.get(new Character(c)); if (value != null) { add(((Character) value).charValue()); } } } else { add(); } } next(); return factory().string(buf.toString()); } private void add(char cc) { buf.append(cc); next(); } private void add() { add(c); } private char unicode() { int value = 0; for (int i = 0; i < 4; ++i) { switch (next()) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': value = (value << 4) + c - '0'; break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': value = (value << 4) + (c - 'a') + 10; break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': value = (value << 4) + (c - 'A') + 10; break; } } return (char) value; } } // END Reader public static void main(String []argv) { try { URI assetUri = new URI("https://raw.githubusercontent.com/pudo/aleph/master/aleph/schema/entity/asset.json"); URI schemaRoot = new URI("https://raw.githubusercontent.com/pudo/aleph/master/aleph/schema/"); // This fails Json.schema(assetUri); // And so does this Json asset = Json.read(assetUri.toURL()); Json.schema(asset, schemaRoot); } catch (Throwable t) { t.printStackTrace(); } } } mjson-1.4.0/src/test/000077500000000000000000000000001277350075000144165ustar00rootroot00000000000000mjson-1.4.0/src/test/java/000077500000000000000000000000001277350075000153375ustar00rootroot00000000000000mjson-1.4.0/src/test/java/testmjson/000077500000000000000000000000001277350075000173655ustar00rootroot00000000000000mjson-1.4.0/src/test/java/testmjson/TU.java000077500000000000000000000006521277350075000205660ustar00rootroot00000000000000package testmjson; import java.net.URL; import java.util.Collection; import java.util.HashSet; import java.util.Set; /** * Created by biordanov on 11/7/2014. */ public class TU { public static Set set(Collection C) { HashSet S = new HashSet(); S.addAll(C); return S; } public static URL resource(String location) { return TU.class.getResource(location); } }mjson-1.4.0/src/test/java/testmjson/TestBasics.java000066400000000000000000000053451277350075000223030ustar00rootroot00000000000000package testmjson; import mjson.Json; import static mjson.Json.*; import org.junit.Test; import org.junit.Assert; public class TestBasics { @Test public void testBoolean() { Json b1 = Json.make(true); Json b1dup = b1.dup(); Assert.assertFalse(b1 == b1dup); Assert.assertEquals(b1, b1dup); Json b2 = Json.factory().bool(Boolean.TRUE); Assert.assertEquals(b1, b2); Assert.assertEquals(Boolean.FALSE, Json.make(false).getValue()); } @Test public void testNil() { Json nil = Json.nil(); Assert.assertEquals(nil, Json.make(null)); Assert.assertNull(nil.getValue()); Json nil2 = nil.dup(); Assert.assertFalse(nil == nil2); Assert.assertEquals(nil, nil2); } @Test public void testNumber() { Json n1 = Json.make(567); Json n2 = Json.make(567.0); Json n1dup = n1.dup(); Assert.assertFalse(n1 == n1dup); Assert.assertEquals(n1, n1dup); Assert.assertEquals(567, n1.asInteger()); Assert.assertEquals(567, n2.asInteger()); Assert.assertEquals(567l, n2.asLong()); Assert.assertEquals(567.0, n2.asFloat(), 0.0); Assert.assertEquals(567.0, n1.asDouble(), 0.0); Assert.assertEquals(n1, n2); Assert.assertEquals(Double.MAX_VALUE, Json.factory().number(Double.MAX_VALUE).getValue()); Assert.assertEquals(Integer.MIN_VALUE, Json.factory().number(Integer.MIN_VALUE).getValue()); } @Test public void testString() { Json s1 = Json.make(""); Assert.assertEquals("", s1.getValue()); Json s1dup = s1.dup(); Assert.assertFalse(s1dup == s1); Assert.assertEquals(s1, s1dup); Json s2 = Json.make("string1"); Json s2again = Json.factory().string("string1"); Assert.assertEquals(s2, s2again); Json s3 = Json.make("Case Sensitive"); Json s3_lower = Json.make("Case Sensitive".toLowerCase()); Assert.assertNotEquals(s3, s3_lower); } @Test public void testArray() { Json empty = array(); Assert.assertTrue(empty.asJsonList().isEmpty()); Json numbers = array(4,3,4); Assert.assertEquals(numbers.at(0), numbers.at(2)); Assert.assertSame(numbers, numbers.add(1)); Assert.assertEquals(4, numbers.asJsonList().size()); Assert.assertEquals(1, numbers.at(3).asInteger()); Json mixed = array(nil(), "s", 2); Assert.assertNull(mixed.at(0).getValue()); Json mixeddup = mixed.dup(); Assert.assertEquals(mixed, mixeddup); Assert.assertEquals("s", mixeddup.at(1).getValue()); } @Test public void testObject() { Json empty = object(); Assert.assertTrue(empty.asJsonMap().isEmpty()); Json o1 = object("p", 1).set("p2", "p2value"); Assert.assertEquals(1, o1.at("p").getValue()); Assert.assertTrue(o1.has("p2")); Assert.assertFalse(o1.has("p2asdfasd")); Json dup = o1.dup(); Assert.assertEquals(o1, dup); dup.set("A", array("23423", 24,2423, o1)); Assert.assertNotEquals(o1, dup); } } mjson-1.4.0/src/test/java/testmjson/TestEnclosing.java000066400000000000000000000027511277350075000230160ustar00rootroot00000000000000package testmjson; import mjson.Json; import static mjson.Json.*; import org.junit.Assert; import org.junit.Test; public class TestEnclosing { @Test public void testParentObject() { Json obj = object(); Json s = make("hi"); obj.set("greet", s); Assert.assertTrue(obj == s.up()); Json nested = object(); obj.set("nested", nested); Assert.assertTrue(obj == nested.up()); nested.set("parent", obj); Assert.assertTrue(nested == obj.up()); Json nested2 = object(); obj.set("nested2", nested2); nested2.set("parent", obj); Assert.assertTrue(obj == nested2.up()); Assert.assertTrue(obj.up().asJsonList().contains(nested2)); } @Test public void testParentArray() { Json arr = array(); Json i = make(10); arr.add(i); Assert.assertTrue(i.up() == arr); System.out.println(i.up()); Json arr2 = array(); arr2.add(i); System.out.println(i.up()); Assert.assertTrue(i.up().asJsonList().contains(arr)); Assert.assertTrue(i.up().asJsonList().contains(arr2)); } @Test public void testToStringOfCircularObject() { Json x = Json.object("name", "x", "tuple", Json.array()); Json y = Json.object("backref", x); x.at("tuple").add(y); String asstring = x.toString(); Assert.assertTrue(asstring.contains("tuple")); } /** * When we duplicate a deeply nested JSON structure, the parent chains must * be properly replicated. */ @Test public void testDuplicateSimpleTree() { } @Test public void testDuplicateGraphWithCycles() { } }mjson-1.4.0/src/test/java/testmjson/TestJsonSchemaSuite.java000066400000000000000000000046771277350075000241520ustar00rootroot00000000000000package testmjson; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; import junit.framework.AssertionFailedError; import mjson.Json; /** * Run a test from the https://github.com/json-schema/JSON-Schema-Test-Suite * test spec. * * @author Borislav Iordanov * */ @RunWith(Parameterized.class) public class TestJsonSchemaSuite { private String group; private String description; private Json.Schema schema; private Json data; private boolean valid; @Parameters public static Collection data() { List tests = new ArrayList(); for (Map.Entry test : TestSchemas.testResources("suite").entrySet()) { Json set = Json.read(test.getValue()); if (!set.isArray()) set = Json.array().add(set); for (Json one : set.asJsonList()) { try { Json.Schema schema = Json.schema(one.at("schema")); for (Json t : one.at("tests").asJsonList()) tests.add(new Object[]{test.getKey(), t.at("description","***").asString() + "/" + one.at("description", "---").asString(), schema, t.at("data"), t.at("valid", true).asBoolean()}); } catch (Throwable t) { throw new RuntimeException("While adding tests from file " + test.getKey() + " - " + one, t); } } } return tests; } public TestJsonSchemaSuite(String group, String description, Json.Schema schema, Json data, boolean valid) { this.group = group; this.description = description; this.schema = schema; this.data = data; this.valid = valid; } @Test public void doTest() { try { System.out.println("Running test " + description + " from " + group); Assert.assertEquals("Running test " + description + " from " + group, valid, schema.validate(data).is("ok", true)); } catch (AssertionFailedError err) // caught so we can break in with debugger here... { schema.validate(data); throw err; } catch (Throwable t) { System.err.println("Exception while running test " + description + " from " + group); } } }mjson-1.4.0/src/test/java/testmjson/TestParser.java000066400000000000000000000060271277350075000223310ustar00rootroot00000000000000package testmjson; import org.junit.Test; import org.junit.runner.JUnitCore; import org.junit.runner.Request; import org.junit.runner.Result; import org.junit.runner.notification.Failure; import org.junit.Assert; import mjson.Json; public class TestParser { @Test(expected=Json.MalformedJsonException.class) public void malformedTest1() { Json.read("{\"value2\":\"years\"\"value3\":\"wtf\"}"); } @Test(expected=Json.MalformedJsonException.class) public void malformedTest2() { Json.read("{\"x\":\"5\",\"y\":\"wtf\""); } @Test(expected=Json.MalformedJsonException.class) public void malformedTest3() { Json.read("{\"value2\"\"years\",\"value3\":\"wtf\"}"); } @Test(expected=Json.MalformedJsonException.class) public void malformedTest4() { Json.read("{\"a\":true, }"); } @Test(expected=Json.MalformedJsonException.class) public void malformedTest5() { Json.read("[43 45]"); } @Test(expected=Json.MalformedJsonException.class) public void malformedTest6() { Json.read("[true, false, ]"); } @Test(expected=Json.MalformedJsonException.class) public void malformedTest7() { Json.read("[true, 10, \"asdf\""); } @Test(expected=Json.MalformedJsonException.class) public void malformedTest8() { Json.read("{[}"); } @Test(expected=Json.MalformedJsonException.class) public void malformedTest9() { Json.read("{\"a\":[}"); } @Test(expected=Json.MalformedJsonException.class) public void malformedTest10() { Json.read("[{]"); } @Test public void parsePrimitives() { Assert.assertEquals(Json.nil(), Json.read("null")); Assert.assertEquals(Json.make(23), Json.read("23")); Assert.assertEquals(Json.make(0.345), Json.read("0.345")); Assert.assertEquals(Json.make(""), Json.read("\"\"")); Assert.assertEquals(Json.make("hell\""), Json.read("\"hell\\\"\"")); Assert.assertEquals(Json.make(true), Json.read("true")); Assert.assertEquals(Json.make(false), Json.read("false")); } @Test public void parseArrays() { Assert.assertEquals(Json.array(), Json.read("[]")); Assert.assertEquals(Json.array(1,2,3), Json.read("[1,2,3]")); Assert.assertEquals(Json.array(10.3,"blabla", true), Json.read("[10.3, \"blabla\", true]")); } @Test public void parseObjects() { Assert.assertEquals(Json.object(), Json.read("{}")); Assert.assertEquals(Json.object("one", 1, "maybe", false, "nothing", null), Json.read("\t{\"one\":1, \t \"maybe\":false , \n\n\"nothing\" : null} ")); } @Test public void parseSomeDeepStructures() { Json j1 = Json.read(TU.resource("/parseme1.json")); j1.is("ok", true); j1.at("doc").at("content").at(0).is("type", "discourseContainer"); Assert.assertEquals(Json.array(Json.object(), Json.object("x", null), null), Json.read("[{},{\"x\":null},null]")); } public static void main(String [] argv) { JUnitCore junit = new JUnitCore(); Result result = null; result = junit.run(Request.method(TestParser.class, "malformedTest4")); if (result.getFailureCount() > 0) { for (Failure failure : result.getFailures()) { failure.getException().printStackTrace(); } } System.exit(0); } } mjson-1.4.0/src/test/java/testmjson/TestSchemas.java000077500000000000000000000171421277350075000224630ustar00rootroot00000000000000package testmjson; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import org.junit.Assert; import org.junit.Test; import mjson.Json; /** * * @author Borislav Iordanov * */ public class TestSchemas { public static byte[] getBytesFromStream(InputStream is, boolean close) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); try { byte[] A = new byte[4096]; // Read in the bytes for (int cnt = is.read(A); cnt > -1; cnt = is.read(A)) out.write(A, 0, cnt); return out.toByteArray(); // Close the input stream and return bytes } finally { if (close) is.close(); } } public static String readFile(File file) { InputStream in = null; try { in = new FileInputStream(file); return new String(getBytesFromStream(in, true)); } catch (IOException e) { throw new RuntimeException(e); } finally { if (in != null) try { in.close(); } catch (Throwable t) { } } } public static String readTextResource(String resource) { InputStream in = TestSchemas.class.getResourceAsStream(resource); if (in == null) return null; else try { return new String(getBytesFromStream(in, true)); } catch (IOException e) { throw new RuntimeException(e); } } // this won't work for jar files probably, for test classes&resources are usually not bundled // in jars... public static Map testResources(String name) { HashMap L = new HashMap(); try { Enumeration en = TestSchemas.class.getClassLoader().getResources(name); if (en.hasMoreElements()) { URL resource = en.nextElement(); File resourceFile = new File(resource.toURI()); if (resourceFile.isDirectory()) for (String nested : resourceFile.list()) { File nestedFile = new File(resourceFile, nested); if (nestedFile.isDirectory()) L.putAll(testResources(nested)); else L.put(nestedFile.getPath(), readFile(nestedFile)); } else L.put(resourceFile.getPath(), readFile(resourceFile)); // File[] files = resourceFile.listFiles(); // String[] filenames = fileMetaInf.list(); } } catch (Exception ex) { throw new RuntimeException(ex); } return L; } /** * Test a schema against a document that should validate and then * against a document that should fail to validate. * @param schema * @param correct * @param incorrect */ public void doTest(Json schema, Json correct, Json incorrect) { doTest(Json.schema(schema), correct, incorrect); } /** * Test a schema against a document that should validate and then * against a document that should fail to validate. * @param schema * @param correct * @param incorrect */ public void doTest(Json.Schema schema, Json correct, Json incorrect) { Json ok = Json.nil(); if (correct != null) { ok = schema.validate(correct); Assert.assertTrue(ok.at("errors", "").toString(), ok.at("ok").asBoolean()); } if (incorrect != null) { ok = schema.validate(incorrect); Assert.assertFalse(ok.at("ok").asBoolean()); } } @Test public void testType() { doTest(Json.object("type", "string"), Json.make("asdfasd"), Json.array()); doTest(Json.object("type", "array"), Json.array(), Json.make("asdfasd")); doTest(Json.object("type", "object"), Json.object("asdf",23423), Json.nil()); doTest(Json.object("type", "boolean"), Json.make(true), Json.object("asdf",23423)); doTest(Json.object("type", "null"), Json.nil(), Json.make(false)); doTest(Json.object("type", "number"), Json.make(23423.5345), Json.make("gdfgsdf")); doTest(Json.object("type", "integer"), Json.make(5345), Json.make(5345.534)); doTest(Json.object("type", "any"), Json.make(5345), null); doTest(Json.object("type", "any"), Json.make("Gasgfdsf"), null); doTest(Json.object("type", "any"), Json.array(), null); } @Test public void testEnum() { doTest(Json.object("enum", Json.array(null, 42, "hi", Json.object("a", 10))), Json.make(42), Json.make("blabla")); doTest(Json.object("enum", Json.array(null, 42, "hi", Json.object("a", 10))), Json.object().set("a", 10), Json.array(10)); doTest(Json.object("enum", Json.array(null, 42, "hi", Json.object("a", 10))), Json.make("hi"), Json.object("a", "hi")); } @Test public void testSchemaWithDefs() throws URISyntaxException { Json.Schema schema = Json.schema(TU.resource("/schemas_data/schema_with_defs.json").toURI()); Json data = Json.array(Json.object()); Json result = schema.validate(data); if (!result.is("ok", true)) { System.err.println(result.at("errors")); Assert.fail(); } } @Test public void testOpenCirmSchema() throws URISyntaxException { Json.Schema schema = Json.schema(TU.resource("/schemas_data/json_case_schema.json").toURI()); Json data = Json.read(TU.resource("/schemas_data/json_data.json")); Json result = schema.validate(data); if (!result.is("ok", true)) { System.err.println(result.at("errors")); Assert.fail(); } } public Object[] addTests() { List tests = new ArrayList(); for (Map.Entry test : testResources("suite").entrySet()) { Json set = Json.read(test.getValue()); if (!set.isArray()) set = Json.array().add(set); for (Json one : set.asJsonList()) { try { Json.Schema schema = Json.schema(one.at("schema")); for (Json t : one.at("tests").asJsonList()) tests.add(new TestJsonSchemaSuite(test.getKey(), t.at("description","***").asString() + "/" + one.at("description", "---").asString(), schema, t.at("data"), t.at("valid", true).asBoolean())); } catch (Throwable t) { throw new RuntimeException("While adding tests from file " + test.getKey() + " - " + one, t); } } } return tests.toArray(); } public static void main(String [] argv) { // String content = TestSchemas.readFile(new File("c:/work/mjson/schema.json")); // Json j = Json.read(content); // System.out.println(j.toString()); // Json.schema(Json.object( // "$ref","https://raw.githubusercontent.com/json-schema/JSON-Schema-Test-Suite/develop/remotes/subSchemas.json#/refToInteger" // )); Json set = Json.read(readTextResource("/suite/ref.json")); for (Json one : set.asJsonList()) { Json.Schema schema = Json.schema(one.at("schema")); //System.out.println(one.at("schema")); for (Json t : one.at("tests").asJsonList()) { TestJsonSchemaSuite thetest = new TestJsonSchemaSuite("properties", t.at("description","***").asString() + "/" + one.at("description", "---").asString(), schema, t.at("data"), t.at("valid", true).asBoolean()); try { thetest.doTest(); } catch (Throwable ex) { System.out.println("Failed at " + t); ex.printStackTrace(); System.exit(-1); } } } // TestSchemas test = new TestSchemas(); // test.setUp(); // test.testType(); } } mjson-1.4.0/src/test/java/testmjson/TestWithOptions.java000077500000000000000000000036741277350075000233740ustar00rootroot00000000000000package testmjson; import mjson.Json; import static mjson.Json.*; import org.junit.Assert; import org.junit.Test; /** * Created by biordanov on 10/31/2014. */ public class TestWithOptions { @Test public void testObjectMerge() { Json o1 = object("id", 2, "name", "John", "address", object("streetName", "Main", "streetNumber", 20, "city","Detroit")); Json o2 = o1.dup().set("age", 20).at("address").delAt("city").up(); o1.with(o2, "merge"); Assert.assertTrue(o1.is("age", 20)); Assert.assertTrue(o1.at("address").is("city", "Detroit")); } @Test public void testSortedArrayMerge() { Json a1 = array(1,2,20,30,50); Json a2 = array(0, 2, 20, 30, 35, 40, 51); a1.with(a2, "sort"); Assert.assertEquals(array(0, 1, 2, 20, 30, 35, 40, 50, 51), a1); } @Test public void testUnsortedArrayMerge() { Json a1 = array(4, 35, 1, 65, 2, 456); Json a2 = array(65, 5, 3534, 4); a1.with(a2, object("sort", false)); Assert.assertEquals(TU.set(a1.asJsonList()), TU.set(array(4, 35, 1, 65, 2, 456, 65, 5, 3534, 4).asJsonList())); } @Test public void testCompareEqualsInObject() { Json x1 = object("id", 4, "name", "Tom"); Json x2 = object("id", 4, "name", "Hanna"); Json a1 = array(object("person", x1)); Json a2 = array(object("person", x2)); a1.with(a2, new Json[0]); Assert.assertEquals(2, a1.asJsonList().size()); a1 = array(object("person", x1)); a1.with(a2, object("compareBy", "id")); Assert.assertEquals(1, a1.asJsonList().size()); Assert.assertEquals(make("Tom"), a1.at(0).at("person").at("name")); } @Test public void testCompareEqualsInArray() { } @Test public void testCompareOrderArray() { } }mjson-1.4.0/src/test/resources/000077500000000000000000000000001277350075000164305ustar00rootroot00000000000000mjson-1.4.0/src/test/resources/parseme1.json000066400000000000000000000017251277350075000210450ustar00rootroot00000000000000{"doc":{"marks":[],"type":"doc","content":[{"marks":[],"type":"discourseContainer","content":[{"marks":[],"type":"paragraph","content":[{"text":"Here is our first appearance of Joe Dunkin, a prominent character in the story. ","marks":[],"type":"text","attrs":{}}],"attrs":{}},{"marks":[],"type":"paragraph","content":[],"attrs":{}}],"attrs":{"hghandle":"80177f54-2bb8-4975-be57-b32c04b23c40","title":"Chapter 1","owlclass":"http://purl.org/spar/doco/Chapter"}},{"marks":[],"type":"discourseContainer","content":[{"marks":[],"type":"paragraph","content":[{"text":"As the events unfold, Joe visits the newly open Frog Leg restaurant where one finds every unimaginable exotic food, except frog legs of course.","marks":[],"type":"text","attrs":{}}],"attrs":{}}],"attrs":{"hghandle":"c0cd4f1a-38e1-4576-b938-5330da612463","title":"Chapter 2","owlclass":"http://purl.org/spar/doco/Chapter"}}],"attrs":{"name":"TestSample1","hghandle":"5d840cee-5eb0-41fa-899d-fa1239299f26"}},"ok":true}mjson-1.4.0/src/test/resources/schemas_data/000077500000000000000000000000001277350075000210445ustar00rootroot00000000000000mjson-1.4.0/src/test/resources/schemas_data/json_case_schema.json000066400000000000000000000414351277350075000252320ustar00rootroot00000000000000{ "$schema": "http://json-schema.org/draft-04/schema#", "description": "schema for an Service Case question list", "items": { "$ref": "#/definitions/ServiceField"}, "minItems": 1, "uniqueItems": true, "type": "array", "definitions":{ "ServiceField": { "type": "object", "oneOf": [ {"$ref": "#/definitions/ServiceNote"}, {"$ref": "#/definitions/ServiceQuestion"} ] }, "ServiceFieldList": { "items": { "$ref": "#/definitions/ServiceField"}, "minItems": 1, "uniqueItems": true, "type": "array" }, "ServiceNote": { "additionalProperties": false, "properties": { "iri": {"$ref": "#/definitions/iri"}, "label": {"$ref": "#/definitions/label"}, "hasAllowableModules": {"$ref": "#/definitions/hasAllowableModules"}, "hasBusinessCodes": {"$ref": "#/definitions/hasBusinessCodes"}, "hasDataType": {"$ref": "#/definitions/hasDataType"}, "hasLegacyCode": {"$ref": "#/definitions/hasLegacyCode"}, "hasOrderBy": {"$ref": "#/definitions/hasOrderBy"}, "hasChoiceValueList": {"$ref": "#/definitions/hasChoiceValueList"}, "hasDataSource": {"$ref": "#/definitions/hasDataSource"}, "isDisabled": {"$ref": "#/definitions/isDisabled"}, "type": { "enum": ["ServiceNote"] } }, "required": [ "iri", "label", "hasDataType", "hasOrderBy", "type" ], "type": "object" }, "ServiceQuestion": { "additionalProperties": false, "properties": { "iri": {"$ref": "#/definitions/iri"}, "label": {"$ref": "#/definitions/label"}, "hasAllowableModules": {"$ref": "#/definitions/hasAllowableModules"}, "hasBusinessCodes": {"$ref": "#/definitions/hasBusinessCodes"}, "hasDataType": {"$ref": "#/definitions/hasDataType"}, "hasLegacyCode": {"$ref": "#/definitions/hasLegacyCode"}, "hasOrderBy": {"$ref": "#/definitions/hasOrderBy"}, "hasChoiceValueList": {"$ref": "#/definitions/hasChoiceValueList"}, "hasServiceFieldAlert": {"$ref": "#/definitions/hasServiceFieldAlert"}, "isDisabled": {"$ref": "#/definitions/isDisabled"}, "hasDefaultIntakeMethod": {"$ref": "#/definitions/hasDefaultIntakeMethod"}, "hasStandardizeStreetFormat": {"$ref": "#/definitions/hasStandardizeStreetFormat"}, "hasLegacyEvent": {"$ref": "#/definitions/hasLegacyEvent"}, "hasActivityAssignment": {"$ref": "#/definitions/hasActivityAssignment"}, "type": { "enum": ["ServiceQuestion"] } }, "required": [ "iri", "label", "hasDataType", "hasOrderBy", "type" ], "type": "object" }, "hasStandardizeStreetFormat": { "enum": ["true","false"] }, "isDisabled": { "enum": ["true","false"] }, "booleanValue": { "enum": ["true","false"] }, "hasBusinessCodes": { "pattern": "^,?(((NOUPDATE|REQINTAK|FQ_ALERT|SUCCESSR|WEBQREQD|5DAYWORK|INSSPEC|DUPSTAFF|REQRESAC|REQMASS),?)*)+$", "type": "string" }, "hasOrderBy": { "pattern": "^[-+]?[0-9]*.?[0-9]+$", "type": "string" }, "floatNumber": { "pattern": "^[-+]?[0-9]*.?[0-9]+$", "type": "string" }, "label": { "type": "string" }, "hasAllowableModules": { "pattern": "^,?(((SREINTAK|SRERESAC|SREMASS|SRSNGLWO|SRSUMMRY|WEBINTAK|SRSUMMRY|MD-WCS|MD-WCSL),?)*)+$", "type": "string" }, "iri": { "type": "string" }, "hasLegacyCode": { "type": "string" }, "hasServiceFieldAlert": { "oneOf":[ {"$ref": "#/definitions/hasServiceFieldAlertList"}, {"$ref": "#/definitions/ServiceFieldAlert"} ] }, "hasServiceFieldAlertList": { "items": { "type": "object", "oneOf":[ {"$ref": "#/definitions/ServiceFieldAlert"} ] }, "minItems": 1, "type": "array" }, "ServiceFieldAlert": { "properties": { "hasLegacyEvent": {"$ref": "#/definitions/hasLegacyEvent"}, "hasAnswerObject": {"$ref": "#/definitions/hasAnswerObject"}, "label": {"$ref": "#/definitions/label"}, "type": { "enum": ["QuestionTrigger"] }, "iri": {"$ref": "#/definitions/iri"} }, "required": [ "iri", "label", "hasLegacyEvent", "type" ], "type": "object" }, "hasDataType": { "enum": [ "TIME", "CHAR", "DATE", "NUMBER", "CHARLIST", "CHARMULT", "CHAROPT", "PHONENUM" ] }, "hasChoiceValueList": { "type": "object", "properties": { "hasChoiceValue": { "oneOf":[ {"$ref": "#/definitions/ChoiceValue"}, {"$ref": "#/definitions/ListOfChoiceValues"} ] }, "label": {"$ref": "#/definitions/label"}, "iri": {"$ref": "#/definitions/iri"}, "type": { "enum": ["ChoiceValueList"] } }, "required": [ "iri", "label", "hasChoiceValue", "type" ] }, "hasChoiceValue": { "oneOf":[ {"$ref": "#/definitions/ChoiceValue"}, {"$ref": "#/definitions/ListOfChoiceValues"} ] }, "ListOfChoiceValues": { "items": { "type": "object", "oneOf":[ {"$ref": "#/definitions/ChoiceValue"} ] }, "minItems": 1, "type": "array" }, "ChoiceValue": { "type": "object", "additionalProperties": false, "properties": { "label": {"$ref": "#/definitions/label"}, "iri": {"$ref": "#/definitions/iri"}, "hasLegacyCode": {"$ref": "#/definitions/hasLegacyCode"}, "hasOrderBy": {"$ref": "#/definitions/hasOrderBy"}, "isDisabled": {"$ref": "#/definitions/isDisabled"}, "hasLegacyEvent": {"$ref": "#/definitions/hasLegacyEvent"}, "type": { "enum": ["ChoiceValue"] } }, "required": [ "iri", "label", "type" ] }, "ynQuestion": { "enum": [ "Y", "N" ] }, "hasDefaultIntakeMethod": { "type": "object", "properties": { "hasOrderBy": {"$ref": "#/definitions/hasOrderBy"}, "hasLegacyCode": {"$ref": "#/definitions/hasLegacyCode"}, "label": {"$ref": "#/definitions/label"}, "isAlwaysPublic": {"$ref": "#/definitions/ynQuestion"}, "type": { "enum": ["IntakeMethod"] }, "iri": {"$ref": "#/definitions/iri"} }, "required": [ "iri", "label", "hasLegacyCode", "type" ] }, "hasLegacyInterface": { "items": { "type": "object" }, "minItems": 1, "type": "array" }, "hasLegacyEvent": { "oneOf":[ {"$ref": "#/definitions/LegacyEventObject"}, {"$ref": "#/definitions/ListOfLegacyEventObject"} ] }, "ListOfLegacyEventObject": { "items": { "type": "object", "oneOf":[ {"$ref": "#/definitions/LegacyEventObject"} ] }, "minItems": 1, "type": "array" }, "LegacyEventObject": { "type": "object", "properties": { "label": {"$ref": "#/definitions/label"}, "type": { "enum": ["ServiceFieldAlert","ClearServiceField","MarkServiceFieldRequired","MarkServiceFieldDisabled","ActivityAssignment","StatusChange"] }, "iri": {"$ref": "#/definitions/iri"}, "hasServiceField": {"$ref": "#/definitions/ServiceFieldList"}, "hasActivity": {"$ref": "#/definitions/Activity"}, "hasStatus": {"$ref": "#/definitions/hasStatus"} } }, "hasStatus": { "type": "object", "properties": { "label": {"$ref": "#/definitions/label"}, "type": { "enum": ["Status"] }, "iri": {"$ref": "#/definitions/iri"}, "hasLegacyCode": {"$ref": "#/definitions/hasLegacyCode"}, "hasOrderBy": {"$ref": "#/definitions/hasOrderBy"}, "hasAllowableStatuses": {"$ref": "#/definitions/hasAllowableStatuses"}, "isAlwaysPublic": {"$ref": "#/definitions/ynQuestion"} } }, "hasAllowableStatuses": { "pattern": "^,?(((C-CLOSED|O-OPEN|O-PENDING),?)*)+$", "type": "string" }, "Activity": { "type": "object", "properties": { "label": {"$ref": "#/definitions/label"}, "type": { "enum": ["Activity"] }, "iri": {"$ref": "#/definitions/iri"}, "hasLegacyCode": {"$ref": "#/definitions/hasLegacyCode"}, "hasOrderBy": {"$ref": "#/definitions/hasOrderBy"}, "hasBusinessCodes": {"$ref": "#/definitions/hasBusinessCodes"}, "hasOccurDays": {"$ref": "#/definitions/floatNumber"}, "hasSuspenseDays": {"$ref": "#/definitions/floatNumber"}, "isAutoCreate": {"$ref": "#/definitions/ynQuestion"}, "isAutoAssign": {"$ref": "#/definitions/booleanValue"}, "hasAllowableOutcome": {"$ref": "#/definitions/Outcome"}, "hasDefaultOutcome": {"$ref": "#/definitions/Outcome"}, "hasAssignmentRule": {"$ref": "#/definitions/hasAssignmentRule"}, "hasActivityAssignment": {"$ref": "#/definitions/hasActivityAssignment"} } }, "hasAssignmentRule": { "type": "object", "properties": { "label": {"$ref": "#/definitions/label"}, "type": { "enum": ["AssignActivityToUserRule", "CaseActivityAssignmentRule"] }, "iri": {"$ref": "#/definitions/iri"}, "hasUsername": {"$ref": "#/definitions/username"} } }, "Outcome": { "oneOf":[ {"$ref": "#/definitions/OutcomeObject"}, {"$ref": "#/definitions/ListOfOutcomeObject"} ] }, "ListOfOutcomeObject": { "items": { "type": "object", "oneOf":[ {"$ref": "#/definitions/OutcomeObject"} ] }, "minItems": 1, "type": "array" }, "OutcomeObject": { "type": "object", "properties": { "label": {"$ref": "#/definitions/label"}, "hasLegacyCode": {"$ref": "#/definitions/hasLegacyCode"}, "hasLegacyEvent": {"$ref": "#/definitions/hasLegacyEvent"}, "type": { "enum": ["Outcome"] }, "iri": {"$ref": "#/definitions/iri"} } }, "hasActivityAssignment": { "oneOf":[ {"$ref": "#/definitions/ActivityAssignmentObject"}, {"$ref": "#/definitions/ListOfActivityAssignmentObject"} ] }, "ListOfActivityAssignmentObject": { "items": { "type": "object", "oneOf":[ {"$ref": "#/definitions/ActivityAssignmentObject"} ] }, "minItems": 1, "type": "array" }, "ActivityAssignmentObject": { "type": "object", "properties": { "label": {"$ref": "#/definitions/label"}, "hasActivity": {"$ref": "#/definitions/Activity"}, "hasOutcome": {"$ref": "#/definitions/Outcome"}, "hasLegacyEvent": {"$ref": "#/definitions/hasLegacyEvent"}, "hasAnswerObject": {"$ref": "#/definitions/hasAnswerObject"}, "type": { "enum": ["Activity Trigger", "QuestionTrigger"] }, "iri": {"$ref": "#/definitions/iri"} } }, "username": { "type": "string" }, "hasAnswerObject": { "type": "object", "properties": { "hasLegacyCode": {"$ref": "#/definitions/hasLegacyCode"}, "label": {"$ref": "#/definitions/label"}, "type": { "enum": ["ChoiceValue"] }, "iri": {"$ref": "#/definitions/iri"}, "hasLegacyEvent": {"$ref": "#/definitions/hasLegacyEvent"} }, "required": [ "iri", "label", "hasLegacyCode", "type" ] }, "hasDataSource": { "type": "object", "properties": { "providedBy": {"$ref": "#/definitions/providedBy"}, "label": {"$ref": "#/definitions/label"}, "type": { "enum": ["EventBasedDataSource"] }, "iri": {"$ref": "#/definitions/iri"}, "hasPropertyName": {"$ref": "#/definitions/label"} }, "required": [ "iri", "label", "providedBy", "hasPropertyName", "type" ] }, "providedBy": { "type": "object", "properties": { "label": {"$ref": "#/definitions/label"}, "type": { "enum": ["ClientSideEventType"] }, "iri": {"$ref": "#/definitions/iri"} }, "required": [ "iri", "label", "type" ] } } }mjson-1.4.0/src/test/resources/schemas_data/json_data.json000066400000000000000000000722751277350075000237160ustar00rootroot00000000000000[ { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_PWNOTE1", "hasLegacyCode": "PWNOTE1", "hasAllowableModules": ",WEBINTAK,", "hasDataType": "CHAR", "label": "If Location/Property, previously entered address will be used.", "hasBusinessCodes": ",NOUPDATE,", "hasOrderBy": "0.02", "isDisabled": "true", "type": "ServiceNote" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_PWNOTE2", "hasLegacyCode": "PWNOTE2", "hasAllowableModules": ",WEBINTAK,", "hasDataType": "CHAR", "label": "If Intersection, enter streets in Street 1 and Street 2.", "hasBusinessCodes": ",NOUPDATE,", "hasOrderBy": "0.04", "type": "ServiceNote" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_PWNOTE3", "hasLegacyCode": "PWNOTE3", "hasAllowableModules": ",WEBINTAK,", "hasDataType": "CHAR", "label": "Corridor is a street between 2 cross streets. Enter in Streets 1,2,3.", "hasBusinessCodes": ",NOUPDATE,", "hasOrderBy": "0.06", "type": "ServiceNote" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_PWNOTE4", "hasLegacyCode": "PWNOTE4", "hasAllowableModules": ",WEBINTAK,", "hasDataType": "CHAR", "label": "An Area is surrounded by 4 streets (a block). Use all 4 Street fields.", "hasBusinessCodes": ",NOUPDATE,", "hasOrderBy": "0.08", "type": "ServiceNote" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS1", "hasLegacyCode": "GIS1", "hasChoiceValueList": { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS1_QALOCTYP", "hasChoiceValue": [ { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS1_QALOCTYP_QALOCARE", "hasLegacyCode": "QALOCARE", "label": "Area", "hasOrderBy": "5.0", "hasLegacyEvent": { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS1_ARE_EVENT", "label": "PW702_GIS1_ARE_EVENT", "hasServiceField": [ { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS2", "hasLegacyCode": "GIS2", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 1", "hasOrderBy": "0.2", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS3", "hasLegacyCode": "GIS3", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 2", "hasOrderBy": "0.3", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS4", "hasLegacyCode": "GIS4", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 3", "hasOrderBy": "0.4", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS5", "hasLegacyCode": "GIS5", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 4", "hasOrderBy": "0.5", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" } ], "type": "MarkServiceFieldRequired" }, "type": "ChoiceValue" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS1_QALOCTYP_QALOCCOR", "hasLegacyCode": "QALOCCOR", "label": "Corridor", "hasOrderBy": "4.0", "hasLegacyEvent": { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS1_COR_EVENT", "label": "PW702_GIS1_COR_EVENT", "hasServiceField": [ { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS2", "hasLegacyCode": "GIS2", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 1", "hasOrderBy": "0.2", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS3", "hasLegacyCode": "GIS3", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 2", "hasOrderBy": "0.3", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS4", "hasLegacyCode": "GIS4", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 3", "hasOrderBy": "0.4", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" } ], "type": "MarkServiceFieldRequired" }, "type": "ChoiceValue" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS1_QALOCTYP_QALOCINT", "hasLegacyCode": "QALOCINT", "label": "Intersection", "hasOrderBy": "2.0", "hasLegacyEvent": { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS1_INT_EVENT", "label": "PW702_GIS1_INT_EVENT", "hasServiceField": [ { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS2", "hasLegacyCode": "GIS2", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 1", "hasOrderBy": "0.2", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS3", "hasLegacyCode": "GIS3", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 2", "hasOrderBy": "0.3", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" } ], "type": "MarkServiceFieldRequired" }, "type": "ChoiceValue" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS1_QALOCTYP_QALOCLOC", "hasLegacyCode": "QALOCLOC", "label": "Location/Property", "hasOrderBy": "1.0", "hasLegacyEvent": { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS1_LOC_EVENT", "label": "PW702_GIS1_LOC_EVENT", "hasServiceField": [ { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS2", "hasLegacyCode": "GIS2", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 1", "hasOrderBy": "0.2", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS3", "hasLegacyCode": "GIS3", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 2", "hasOrderBy": "0.3", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS4", "hasLegacyCode": "GIS4", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 3", "hasOrderBy": "0.4", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS5", "hasLegacyCode": "GIS5", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 4", "hasOrderBy": "0.5", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" } ], "type": "MarkServiceFieldDisabled" }, "type": "ChoiceValue" } ], "label": "PW702_GIS1_QALOCTYP", "type": "ChoiceValueList" }, "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasServiceFieldAlert": [ { "iri": "http://www.miamidade.gov/cirm/legacy#152873259", "hasLegacyEvent": { "iri": "http://www.miamidade.gov/cirm/legacy#152873284", "label": "For Area (surrounded by 4 streets such as a block), you must complete all 4 Street \nfields: Street1, Street2, Street3, Street4; (i.e. SW 137th Ave = Street1, SW 138th Ave \n= Street2, SW 38th St = Street3, SW 40th St = Street4", "type": "ServiceFieldAlert" }, "label": "152873259", "type": "QuestionTrigger", "hasAnswerObject": { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS1_QALOCTYP_QALOCARE", "hasLegacyCode": "QALOCARE", "label": "Area", "hasLegacyEvent": { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS1_ARE_EVENT", "label": "PW702_GIS1_ARE_EVENT", "hasServiceField": [ { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS2", "hasLegacyCode": "GIS2", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 1", "hasOrderBy": "0.2", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS3", "hasLegacyCode": "GIS3", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 2", "hasOrderBy": "0.3", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS4", "hasLegacyCode": "GIS4", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 3", "hasOrderBy": "0.4", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS5", "hasLegacyCode": "GIS5", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 4", "hasOrderBy": "0.5", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" } ], "type": "MarkServiceFieldRequired" }, "type": "ChoiceValue" } }, { "iri": "http://www.miamidade.gov/cirm/legacy#152873261", "hasLegacyEvent": { "iri": "http://www.miamidade.gov/cirm/legacy#152873286", "label": "For Corridor (between 2 cross streets), you must complete Street1, Street2, & Street3 (i.e. SW 137th Ave = Street1, SW 8th St = Street2, and SW 16th St = Street3)", "type": "ServiceFieldAlert" }, "label": "152873261", "type": "QuestionTrigger", "hasAnswerObject": { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS1_QALOCTYP_QALOCCOR", "hasLegacyCode": "QALOCCOR", "label": "Corridor", "hasLegacyEvent": { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS1_COR_EVENT", "label": "PW702_GIS1_COR_EVENT", "hasServiceField": [ { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS2", "hasLegacyCode": "GIS2", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 1", "hasOrderBy": "0.2", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS3", "hasLegacyCode": "GIS3", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 2", "hasOrderBy": "0.3", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS4", "hasLegacyCode": "GIS4", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 3", "hasOrderBy": "0.4", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" } ], "type": "MarkServiceFieldRequired" }, "type": "ChoiceValue" } }, { "iri": "http://www.miamidade.gov/cirm/legacy#152873263", "hasLegacyEvent": { "iri": "http://www.miamidade.gov/cirm/legacy#152873288", "label": "For Intersection you must complete Street1 and Street2 to reflect the intersection(i.e. SW 137th Ave = Street1 and SW 8th St = Street2)", "type": "ServiceFieldAlert" }, "label": "152873263", "type": "QuestionTrigger", "hasAnswerObject": { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS1_QALOCTYP_QALOCINT", "hasLegacyCode": "QALOCINT", "label": "Intersection", "hasLegacyEvent": { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS1_INT_EVENT", "label": "PW702_GIS1_INT_EVENT", "hasServiceField": [ { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS2", "hasLegacyCode": "GIS2", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 1", "hasOrderBy": "0.2", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS3", "hasLegacyCode": "GIS3", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 2", "hasOrderBy": "0.3", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" } ], "type": "MarkServiceFieldRequired" }, "type": "ChoiceValue" } } ], "hasDataType": "CHARLIST", "label": "Location Type", "hasBusinessCodes": ",REQINTAK,WEBQREQD,FQ_ALERT,SUCCESSR,FQ_ALERT,FQ_ALERT,FQ_ALERT,FQ_ALERT,FQ_ALERT,FQ_ALERT,", "hasOrderBy": "0.1", "hasLegacyEvent": { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS1_CLEAR_EVENT", "label": "PW702_GIS1_CLEAR_EVENT", "hasServiceField": [ { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS2", "hasLegacyCode": "GIS2", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 1", "hasOrderBy": "0.2", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS3", "hasLegacyCode": "GIS3", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 2", "hasOrderBy": "0.3", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS4", "hasLegacyCode": "GIS4", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 3", "hasOrderBy": "0.4", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS5", "hasLegacyCode": "GIS5", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 4", "hasOrderBy": "0.5", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" } ], "type": "ClearServiceField" }, "type": "ServiceQuestion" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS2", "hasLegacyCode": "GIS2", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 1", "hasOrderBy": "0.2", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS3", "hasLegacyCode": "GIS3", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 2", "hasOrderBy": "0.3", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS4", "hasLegacyCode": "GIS4", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 3", "hasOrderBy": "0.4", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS5", "hasLegacyCode": "GIS5", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "Street 4", "hasOrderBy": "0.5", "type": "ServiceQuestion", "hasStandardizeStreetFormat": "true" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS6", "hasLegacyCode": "GIS6", "hasChoiceValueList": { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS6_PWCORR", "hasChoiceValue": [ { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS6_PWCORR_PWCORST1", "hasLegacyCode": "PWCORST1", "label": "1", "type": "ChoiceValue" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS6_PWCORR_PWCORST2", "hasLegacyCode": "PWCORST2", "label": "2", "type": "ChoiceValue" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS6_PWCORR_PWCORST3", "hasLegacyCode": "PWCORST3", "label": "3", "type": "ChoiceValue" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_GIS6_PWCORR_PWCORST4", "hasLegacyCode": "PWCORST4", "label": "4", "type": "ChoiceValue" } ], "label": "PW702_GIS6_PWCORR", "type": "ChoiceValueList" }, "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasDataType": "CHARLIST", "label": "Corridor Primary Street", "hasOrderBy": "0.6", "type": "ServiceQuestion" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_DOESTHIS", "hasLegacyCode": "DOESTHIS", "hasChoiceValueList": { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_DOESTHIS_PWDNONCM", "hasChoiceValue": [ { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_DOESTHIS_PWDNONCM_PWDNON01", "hasLegacyCode": "PWDNON01", "label": "Private Road", "hasOrderBy": "1.0", "type": "ChoiceValue" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_DOESTHIS_PWDNONCM_PWDNON02", "hasLegacyCode": "PWDNON02", "label": "Private Community", "hasOrderBy": "2.0", "type": "ChoiceValue" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_DOESTHIS_PWDNONCM_PWDNON03", "hasLegacyCode": "PWDNON03", "label": "New Development", "hasOrderBy": "3.0", "type": "ChoiceValue" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_DOESTHIS_PWDNONCM_PWDNON04", "hasLegacyCode": "PWDNON04", "label": "Community Under Construction", "hasOrderBy": "4.0", "type": "ChoiceValue" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_DOESTHIS_PWDNONCM_PWDNON05", "hasLegacyCode": "PWDNON05", "label": "None of the above", "hasOrderBy": "5.0", "type": "ChoiceValue" } ], "label": "PW702_DOESTHIS_PWDNONCM", "type": "ChoiceValueList" }, "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasServiceFieldAlert": [ { "iri": "http://www.miamidade.gov/cirm/legacy#188024061", "hasLegacyEvent": { "iri": "http://www.miamidade.gov/cirm/legacy#188024063", "label": "Tell the Citizen that this is the responsibility of the Home Owners Association or the Property Manager. \nCLEAR THIS SR.", "type": "ServiceFieldAlert" }, "label": "188024061", "type": "QuestionTrigger", "hasAnswerObject": { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_DOESTHIS_PWDNONCM_PWDNON01", "hasLegacyCode": "PWDNON01", "label": "Private Road", "type": "ChoiceValue" } }, { "iri": "http://www.miamidade.gov/cirm/legacy#188024065", "hasLegacyEvent": { "iri": "http://www.miamidade.gov/cirm/legacy#188024067", "label": "Tell the Citizen that this is the responsibility of the Home Owners Association or the Property Manager. \nCLEAR THIS SR.", "type": "ServiceFieldAlert" }, "label": "188024065", "type": "QuestionTrigger", "hasAnswerObject": { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_DOESTHIS_PWDNONCM_PWDNON02", "hasLegacyCode": "PWDNON02", "label": "Private Community", "type": "ChoiceValue" } }, { "iri": "http://www.miamidade.gov/cirm/legacy#188024069", "hasLegacyEvent": { "iri": "http://www.miamidade.gov/cirm/legacy#188024071", "label": "Tell the Citizen that this is the responsibility of the Construction Company or the Property Manager, \nsince this property may still be under Bond.\nCLEAR THIS SR.", "type": "ServiceFieldAlert" }, "label": "188024069", "type": "QuestionTrigger", "hasAnswerObject": { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_DOESTHIS_PWDNONCM_PWDNON03", "hasLegacyCode": "PWDNON03", "label": "New Development", "type": "ChoiceValue" } }, { "iri": "http://www.miamidade.gov/cirm/legacy#188024073", "hasLegacyEvent": { "iri": "http://www.miamidade.gov/cirm/legacy#188024075", "label": "CALL-TAKER: CHANGE THIS SR TYPE TO: \n\nNEW DEVELOPMENT/SUBDIVISION CONSTRUCTION COMPLAINT", "type": "ServiceFieldAlert" }, "label": "188024073", "type": "QuestionTrigger", "hasAnswerObject": { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_DOESTHIS_PWDNONCM_PWDNON04", "hasLegacyCode": "PWDNON04", "label": "Community Under Construction", "type": "ChoiceValue" } } ], "hasDataType": "CHAROPT", "label": "Does this road meet any of the following criteria?", "hasBusinessCodes": ",FQ_ALERT,REQINTAK,SUCCESSR,WEBQREQD,FQ_ALERT,FQ_ALERT,FQ_ALERT,FQ_ALERT,", "hasOrderBy": "0.9", "type": "ServiceQuestion" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_Q1", "hasLegacyCode": "Q1", "hasChoiceValueList": { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_Q1_YESNO1", "hasChoiceValue": [ { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_Q1_YESNO1_NO", "hasLegacyCode": "NO", "label": "No", "type": "ChoiceValue" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_Q1_YESNO1_YES", "hasLegacyCode": "YES", "label": "Yes", "type": "ChoiceValue" } ], "label": "PW702_Q1_YESNO1", "type": "ChoiceValueList" }, "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,WEBINTAK,", "hasServiceFieldAlert": { "iri": "http://www.miamidade.gov/cirm/legacy#152873277", "hasLegacyEvent": { "iri": "http://www.miamidade.gov/cirm/legacy#152873290", "label": "CALL TAKER: Please Change the SR Type to: PEDESTRIAN RAMP ( NOT ADA RELATED )", "type": "ServiceFieldAlert" }, "label": "152873277", "type": "QuestionTrigger", "hasAnswerObject": { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_Q1_YESNO1_NO", "hasLegacyCode": "NO", "label": "No", "type": "ChoiceValue" } }, "hasDataType": "CHAROPT", "label": "Does a disabled person reside at this location?", "hasBusinessCodes": ",FQ_ALERT,SUCCESSR,", "hasOrderBy": "1.0", "type": "ServiceQuestion" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_Q2", "hasLegacyCode": "Q2", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,", "hasDataType": "CHAR", "label": "What is the desired route?", "hasOrderBy": "2.0", "type": "ServiceQuestion" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_Q3", "hasLegacyCode": "Q3", "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,", "hasDataType": "CHAR", "label": "Where do you want to go?", "hasOrderBy": "3.0", "type": "ServiceQuestion" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_Q4", "hasLegacyCode": "Q4", "hasChoiceValueList": { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_Q4_YESNO1", "hasChoiceValue": [ { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_Q4_YESNO1_NO", "hasLegacyCode": "NO", "label": "No", "type": "ChoiceValue" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_Q4_YESNO1_YES", "hasLegacyCode": "YES", "label": "Yes", "type": "ChoiceValue" } ], "label": "PW702_Q4_YESNO1", "type": "ChoiceValueList" }, "hasAllowableModules": ",SREINTAK,SREMASS,SRERESAC,SRSNGLWO,SRSUMMRY,", "hasDataType": "CHAROPT", "label": "Is there an existing sidewalk?", "hasOrderBy": "4.0", "type": "ServiceQuestion" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_THISSRSH", "hasLegacyCode": "THISSRSH", "hasAllowableModules": ",SREINTAK,SRERESAC,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "This SR should be inspected within 30 business days.", "hasBusinessCodes": ",NOUPDATE,", "hasOrderBy": "98.0", "type": "ServiceNote" }, { "iri": "http://www.miamidade.gov/cirm/legacy#PW702_YOUMAYCA", "hasLegacyCode": "YOUMAYCA", "hasAllowableModules": ",SREINTAK,SRERESAC,SRSUMMRY,WEBINTAK,", "hasDataType": "CHAR", "label": "You may call for an update in 30 days.", "hasBusinessCodes": ",NOUPDATE,", "hasOrderBy": "99.0", "type": "ServiceNote" } ]mjson-1.4.0/src/test/resources/schemas_data/schema_with_defs.json000066400000000000000000000003101277350075000252250ustar00rootroot00000000000000{ "description":"Testing nested definitions", "definitions":{ "nested" : { "type":"object" } }, "type": "array", "items": { "$ref": "#/definitions/nested"}, "minItems": 1 }mjson-1.4.0/src/test/resources/suite/000077500000000000000000000000001277350075000175615ustar00rootroot00000000000000mjson-1.4.0/src/test/resources/suite/additionalItems.json000066400000000000000000000043521277350075000235720ustar00rootroot00000000000000[ { "description": "additionalItems as schema", "schema": { "items": [{}], "additionalItems": {"type": "integer"} }, "tests": [ { "description": "additional items match schema", "data": [ null, 2, 3, 4 ], "valid": true }, { "description": "additional items do not match schema", "data": [ null, 2, 3, "foo" ], "valid": false } ] }, { "description": "items is schema, no additionalItems", "schema": { "items": {}, "additionalItems": false }, "tests": [ { "description": "all items match schema", "data": [ 1, 2, 3, 4, 5 ], "valid": true } ] }, { "description": "array of items with no additionalItems", "schema": { "items": [{}, {}, {}], "additionalItems": false }, "tests": [ { "description": "no additional items present", "data": [ 1, 2, 3 ], "valid": true }, { "description": "additional items are not permitted", "data": [ 1, 2, 3, 4 ], "valid": false } ] }, { "description": "additionalItems as false without items", "schema": {"additionalItems": false}, "tests": [ { "description": "items defaults to empty schema so everything is valid", "data": [ 1, 2, 3, 4, 5 ], "valid": true }, { "description": "ignores non-arrays", "data": {"foo" : "bar"}, "valid": true } ] }, { "description": "additionalItems are allowed by default", "schema": {"items": [{"type": "integer"}]}, "tests": [ { "description": "only the first item is validated", "data": [1, "foo", false], "valid": true } ] } ] mjson-1.4.0/src/test/resources/suite/additionalProperties.json000066400000000000000000000042221277350075000246410ustar00rootroot00000000000000[ { "description": "additionalProperties being false does not allow other properties", "schema": { "properties": {"foo": {}, "bar": {}}, "patternProperties": { "^v": {} }, "additionalProperties": false }, "tests": [ { "description": "no additional properties is valid", "data": {"foo": 1}, "valid": true }, { "description": "an additional property is invalid", "data": {"foo" : 1, "bar" : 2, "quux" : "boom"}, "valid": false }, { "description": "ignores non-objects", "data": [1, 2, 3], "valid": true }, { "description": "patternProperties are not additional properties", "data": {"foo":1, "vroom": 2}, "valid": true } ] }, { "description": "additionalProperties allows a schema which should validate", "schema": { "properties": {"foo": {}, "bar": {}}, "additionalProperties": {"type": "boolean"} }, "tests": [ { "description": "no additional properties is valid", "data": {"foo": 1}, "valid": true }, { "description": "an additional valid property is valid", "data": {"foo" : 1, "bar" : 2, "quux" : true}, "valid": true }, { "description": "an additional invalid property is invalid", "data": {"foo" : 1, "bar" : 2, "quux" : 12}, "valid": false } ] }, { "description": "additionalProperties are allowed by default", "schema": {"properties": {"foo": {}, "bar": {}}}, "tests": [ { "description": "additional properties are allowed", "data": {"foo": 1, "bar": 2, "quux": true}, "valid": true } ] } ] mjson-1.4.0/src/test/resources/suite/allOf.json000066400000000000000000000057211277350075000215160ustar00rootroot00000000000000[ { "description": "allOf", "schema": { "allOf": [ { "properties": { "bar": {"type": "integer"} }, "required": ["bar"] }, { "properties": { "foo": {"type": "string"} }, "required": ["foo"] } ] }, "tests": [ { "description": "allOf", "data": {"foo": "baz", "bar": 2}, "valid": true }, { "description": "mismatch second", "data": {"foo": "baz"}, "valid": false }, { "description": "mismatch first", "data": {"bar": 2}, "valid": false }, { "description": "wrong type", "data": {"foo": "baz", "bar": "quux"}, "valid": false } ] }, { "description": "allOf with base schema", "schema": { "properties": {"bar": {"type": "integer"}}, "required": ["bar"], "allOf" : [ { "properties": { "foo": {"type": "string"} }, "required": ["foo"] }, { "properties": { "baz": {"type": "null"} }, "required": ["baz"] } ] }, "tests": [ { "description": "valid", "data": {"foo": "quux", "bar": 2, "baz": null}, "valid": true }, { "description": "mismatch base schema", "data": {"foo": "quux", "baz": null}, "valid": false }, { "description": "mismatch first allOf", "data": {"bar": 2, "baz": null}, "valid": false }, { "description": "mismatch second allOf", "data": {"foo": "quux", "bar": 2}, "valid": false }, { "description": "mismatch both", "data": {"bar": 2}, "valid": false } ] }, { "description": "allOf simple types", "schema": { "allOf": [ {"maximum": 30}, {"minimum": 20} ] }, "tests": [ { "description": "valid", "data": 25, "valid": true }, { "description": "mismatch one", "data": 35, "valid": false } ] } ] mjson-1.4.0/src/test/resources/suite/anyOf.json000066400000000000000000000031101277350075000215230ustar00rootroot00000000000000[ { "description": "anyOf", "schema": { "anyOf": [ { "type": "integer" }, { "minimum": 2 } ] }, "tests": [ { "description": "first anyOf valid", "data": 1, "valid": true }, { "description": "second anyOf valid", "data": 2.5, "valid": true }, { "description": "both anyOf valid", "data": 3, "valid": true }, { "description": "neither anyOf valid", "data": 1.5, "valid": false } ] }, { "description": "anyOf with base schema", "schema": { "type": "string", "anyOf" : [ { "maxLength": 2 }, { "minLength": 4 } ] }, "tests": [ { "description": "mismatch base schema", "data": 3, "valid": false }, { "description": "one anyOf valid", "data": "foobar", "valid": true }, { "description": "both anyOf invalid", "data": "foo", "valid": false } ] } ] mjson-1.4.0/src/test/resources/suite/definitions.json000066400000000000000000000015261277350075000227730ustar00rootroot00000000000000[ { "description": "valid definition", "schema": {"$ref": "http://json-schema.org/draft-04/schema#"}, "tests": [ { "description": "valid definition schema", "data": { "definitions": { "foo": {"type": "integer"} } }, "valid": true } ] }, { "description": "invalid definition", "schema": {"$ref": "http://json-schema.org/draft-04/schema#"}, "tests": [ { "description": "invalid definition schema", "data": { "definitions": { "foo": {"type": 1} } }, "valid": false } ] } ] mjson-1.4.0/src/test/resources/suite/dependencies.json000066400000000000000000000061031277350075000231020ustar00rootroot00000000000000[ { "description": "dependencies", "schema": { "dependencies": {"bar": ["foo"]} }, "tests": [ { "description": "neither", "data": {}, "valid": true }, { "description": "nondependant", "data": {"foo": 1}, "valid": true }, { "description": "with dependency", "data": {"foo": 1, "bar": 2}, "valid": true }, { "description": "missing dependency", "data": {"bar": 2}, "valid": false }, { "description": "ignores non-objects", "data": "foo", "valid": true } ] }, { "description": "multiple dependencies", "schema": { "dependencies": {"quux": ["foo", "bar"]} }, "tests": [ { "description": "neither", "data": {}, "valid": true }, { "description": "nondependants", "data": {"foo": 1, "bar": 2}, "valid": true }, { "description": "with dependencies", "data": {"foo": 1, "bar": 2, "quux": 3}, "valid": true }, { "description": "missing dependency", "data": {"foo": 1, "quux": 2}, "valid": false }, { "description": "missing other dependency", "data": {"bar": 1, "quux": 2}, "valid": false }, { "description": "missing both dependencies", "data": {"quux": 1}, "valid": false } ] }, { "description": "multiple dependencies subschema", "schema": { "dependencies": { "bar": { "properties": { "foo": {"type": "integer"}, "bar": {"type": "integer"} } } } }, "tests": [ { "description": "valid", "data": {"foo": 1, "bar": 2}, "valid": true }, { "description": "no dependency", "data": {"foo": "quux"}, "valid": true }, { "description": "wrong type", "data": {"foo": "quux", "bar": 2}, "valid": false }, { "description": "wrong type other", "data": {"foo": 2, "bar": "quux"}, "valid": false }, { "description": "wrong type both", "data": {"foo": "quux", "bar": "quux"}, "valid": false } ] } ] mjson-1.4.0/src/test/resources/suite/enum.json000066400000000000000000000036671277350075000214340ustar00rootroot00000000000000[ { "description": "simple enum validation", "schema": {"enum": [1, 2, 3]}, "tests": [ { "description": "one of the enum is valid", "data": 1, "valid": true }, { "description": "something else is invalid", "data": 4, "valid": false } ] }, { "description": "heterogeneous enum validation", "schema": {"enum": [6, "foo", [], true, {"foo": 12}]}, "tests": [ { "description": "one of the enum is valid", "data": [], "valid": true }, { "description": "something else is invalid", "data": null, "valid": false }, { "description": "objects are deep compared", "data": {"foo": false}, "valid": false } ] }, { "description": "enums in properties", "schema": { "type":"object", "properties": { "foo": {"enum":["foo"]}, "bar": {"enum":["bar"]} }, "required": ["bar"] }, "tests": [ { "description": "both properties are valid", "data": {"foo":"foo", "bar":"bar"}, "valid": true }, { "description": "missing optional property is valid", "data": {"bar":"bar"}, "valid": true }, { "description": "missing required property is invalid", "data": {"foo":"foo"}, "valid": false }, { "description": "missing all properties is invalid", "data": {}, "valid": false } ] } ] mjson-1.4.0/src/test/resources/suite/items.json000066400000000000000000000021601277350075000215740ustar00rootroot00000000000000[ { "description": "a schema given for items", "schema": { "items": {"type": "integer"} }, "tests": [ { "description": "valid items", "data": [ 1, 2, 3 ], "valid": true }, { "description": "wrong type of items", "data": [1, "x"], "valid": false }, { "description": "ignores non-arrays", "data": {"foo" : "bar"}, "valid": true } ] }, { "description": "an array of schemas for items", "schema": { "items": [ {"type": "integer"}, {"type": "string"} ] }, "tests": [ { "description": "correct types", "data": [ 1, "foo" ], "valid": true }, { "description": "wrong types", "data": [ "foo", 1 ], "valid": false } ] } ] mjson-1.4.0/src/test/resources/suite/maxItems.json000066400000000000000000000013021277350075000222370ustar00rootroot00000000000000[ { "description": "maxItems validation", "schema": {"maxItems": 2}, "tests": [ { "description": "shorter is valid", "data": [1], "valid": true }, { "description": "exact length is valid", "data": [1, 2], "valid": true }, { "description": "too long is invalid", "data": [1, 2, 3], "valid": false }, { "description": "ignores non-arrays", "data": "foobar", "valid": true } ] } ] mjson-1.4.0/src/test/resources/suite/maxLength.json000066400000000000000000000016001277350075000224000ustar00rootroot00000000000000[ { "description": "maxLength validation", "schema": {"maxLength": 2}, "tests": [ { "description": "shorter is valid", "data": "f", "valid": true }, { "description": "exact length is valid", "data": "fo", "valid": true }, { "description": "too long is invalid", "data": "foo", "valid": false }, { "description": "ignores non-strings", "data": 100, "valid": true }, { "description": "two supplementary Unicode code points is long enough", "data": "\uD83D\uDCA9\uD83D\uDCA9", "valid": true } ] } ] mjson-1.4.0/src/test/resources/suite/maxProperties.json000066400000000000000000000013671277350075000233250ustar00rootroot00000000000000[ { "description": "maxProperties validation", "schema": {"maxProperties": 2}, "tests": [ { "description": "shorter is valid", "data": {"foo": 1}, "valid": true }, { "description": "exact length is valid", "data": {"foo": 1, "bar": 2}, "valid": true }, { "description": "too long is invalid", "data": {"foo": 1, "bar": 2, "baz": 3}, "valid": false }, { "description": "ignores non-objects", "data": "foobar", "valid": true } ] } ] mjson-1.4.0/src/test/resources/suite/maximum.json000066400000000000000000000020471277350075000221340ustar00rootroot00000000000000[ { "description": "maximum validation", "schema": {"maximum": 3.0}, "tests": [ { "description": "below the maximum is valid", "data": 2.6, "valid": true }, { "description": "above the maximum is invalid", "data": 3.5, "valid": false }, { "description": "ignores non-numbers", "data": "x", "valid": true } ] }, { "description": "exclusiveMaximum validation", "schema": { "maximum": 3.0, "exclusiveMaximum": true }, "tests": [ { "description": "below the maximum is still valid", "data": 2.2, "valid": true }, { "description": "boundary point is invalid", "data": 3.0, "valid": false } ] } ] mjson-1.4.0/src/test/resources/suite/minItems.json000066400000000000000000000012651277350075000222450ustar00rootroot00000000000000[ { "description": "minItems validation", "schema": {"minItems": 1}, "tests": [ { "description": "longer is valid", "data": [1, 2], "valid": true }, { "description": "exact length is valid", "data": [1], "valid": true }, { "description": "too short is invalid", "data": [], "valid": false }, { "description": "ignores non-arrays", "data": "", "valid": true } ] } ] mjson-1.4.0/src/test/resources/suite/minLength.json000066400000000000000000000015661277350075000224110ustar00rootroot00000000000000[ { "description": "minLength validation", "schema": {"minLength": 2}, "tests": [ { "description": "longer is valid", "data": "foo", "valid": true }, { "description": "exact length is valid", "data": "fo", "valid": true }, { "description": "too short is invalid", "data": "f", "valid": false }, { "description": "ignores non-strings", "data": 1, "valid": true }, { "description": "one supplementary Unicode code point is not long enough", "data": "\uD83D\uDCA9", "valid": false } ] } ] mjson-1.4.0/src/test/resources/suite/minProperties.json000066400000000000000000000013251277350075000233150ustar00rootroot00000000000000[ { "description": "minProperties validation", "schema": {"minProperties": 1}, "tests": [ { "description": "longer is valid", "data": {"foo": 1, "bar": 2}, "valid": true }, { "description": "exact length is valid", "data": {"foo": 1}, "valid": true }, { "description": "too short is invalid", "data": {}, "valid": false }, { "description": "ignores non-objects", "data": "", "valid": true } ] } ] mjson-1.4.0/src/test/resources/suite/minimum.json000066400000000000000000000020471277350075000221320ustar00rootroot00000000000000[ { "description": "minimum validation", "schema": {"minimum": 1.1}, "tests": [ { "description": "above the minimum is valid", "data": 2.6, "valid": true }, { "description": "below the minimum is invalid", "data": 0.6, "valid": false }, { "description": "ignores non-numbers", "data": "x", "valid": true } ] }, { "description": "exclusiveMinimum validation", "schema": { "minimum": 1.1, "exclusiveMinimum": true }, "tests": [ { "description": "above the minimum is still valid", "data": 1.2, "valid": true }, { "description": "boundary point is invalid", "data": 1.1, "valid": false } ] } ] mjson-1.4.0/src/test/resources/suite/multipleOf.json000066400000000000000000000027651277350075000226060ustar00rootroot00000000000000[ { "description": "by int", "schema": {"multipleOf": 2}, "tests": [ { "description": "int by int", "data": 10, "valid": true }, { "description": "int by int fail", "data": 7, "valid": false }, { "description": "ignores non-numbers", "data": "foo", "valid": true } ] }, { "description": "by number", "schema": {"multipleOf": 1.5}, "tests": [ { "description": "zero is multiple of anything", "data": 0, "valid": true }, { "description": "4.5 is multiple of 1.5", "data": 4.5, "valid": true }, { "description": "35 is not multiple of 1.5", "data": 35, "valid": false } ] }, { "description": "by small number", "schema": {"multipleOf": 0.0001}, "tests": [ { "description": "0.0075 is multiple of 0.0001", "data": 0.0075, "valid": true }, { "description": "0.00751 is not multiple of 0.0001", "data": 0.00751, "valid": false } ] } ] mjson-1.4.0/src/test/resources/suite/not.json000066400000000000000000000043321277350075000212560ustar00rootroot00000000000000[ { "description": "not", "schema": { "not": {"type": "integer"} }, "tests": [ { "description": "allowed", "data": "foo", "valid": true }, { "description": "disallowed", "data": 1, "valid": false } ] }, { "description": "not multiple types", "schema": { "not": {"type": ["integer", "boolean"]} }, "tests": [ { "description": "valid", "data": "foo", "valid": true }, { "description": "mismatch", "data": 1, "valid": false }, { "description": "other mismatch", "data": true, "valid": false } ] }, { "description": "not more complex schema", "schema": { "not": { "type": "object", "properties": { "foo": { "type": "string" } } } }, "tests": [ { "description": "match", "data": 1, "valid": true }, { "description": "other match", "data": {"foo": 1}, "valid": true }, { "description": "mismatch", "data": {"foo": "bar"}, "valid": false } ] }, { "description": "forbidden property", "schema": { "properties": { "foo": { "not": {} } } }, "tests": [ { "description": "property present", "data": {"foo": 1, "bar": 2}, "valid": false }, { "description": "property absent", "data": {"bar": 1, "baz": 2}, "valid": true } ] } ] mjson-1.4.0/src/test/resources/suite/oneOf.json000066400000000000000000000031071277350075000215230ustar00rootroot00000000000000[ { "description": "oneOf", "schema": { "oneOf": [ { "type": "integer" }, { "minimum": 2 } ] }, "tests": [ { "description": "first oneOf valid", "data": 1, "valid": true }, { "description": "second oneOf valid", "data": 2.5, "valid": true }, { "description": "both oneOf valid", "data": 3, "valid": false }, { "description": "neither oneOf valid", "data": 1.5, "valid": false } ] }, { "description": "oneOf with base schema", "schema": { "type": "string", "oneOf" : [ { "minLength": 2 }, { "maxLength": 4 } ] }, "tests": [ { "description": "mismatch base schema", "data": 3, "valid": false }, { "description": "one oneOf valid", "data": "foobar", "valid": true }, { "description": "both oneOf valid", "data": "foo", "valid": false } ] } ] mjson-1.4.0/src/test/resources/suite/optional/000077500000000000000000000000001277350075000214065ustar00rootroot00000000000000mjson-1.4.0/src/test/resources/suite/optional/bignum.json000066400000000000000000000031771277350075000235720ustar00rootroot00000000000000[ { "description": "integer", "schema": {"type": "integer"}, "tests": [ { "description": "a bignum is an integer", "data": 12345678910111213141516171819202122232425262728293031, "valid": true } ] }, { "description": "number", "schema": {"type": "number"}, "tests": [ { "description": "a bignum is a number", "data": 98249283749234923498293171823948729348710298301928331, "valid": true } ] }, { "description": "string", "schema": {"type": "string"}, "tests": [ { "description": "a bignum is not a string", "data": 98249283749234923498293171823948729348710298301928331, "valid": false } ] }, { "description": "integer comparison", "schema": {"maximum": 18446744073709551615}, "tests": [ { "description": "comparison works for high numbers", "data": 18446744073709551600, "valid": true } ] }, { "description": "float comparison with high precision", "schema": { "maximum": 972783798187987123879878123.18878137, "exclusiveMaximum": true }, "tests": [ { "description": "comparison works for high numbers", "data": 972783798187987123879878123.188781371, "valid": false } ] } ] mjson-1.4.0/src/test/resources/suite/optional/format.json000066400000000000000000000105221277350075000235710ustar00rootroot00000000000000[ { "description": "validation of date-time strings", "schema": {"format": "date-time"}, "tests": [ { "description": "a valid date-time string", "data": "1963-06-19T08:30:06.283185Z", "valid": true }, { "description": "an invalid date-time string", "data": "06/19/1963 08:30:06 PST", "valid": false }, { "description": "only RFC3339 not all of ISO 8601 are valid", "data": "2013-350T01:01:01", "valid": false } ] }, { "description": "validation of URIs", "schema": {"format": "uri"}, "tests": [ { "description": "a valid URI", "data": "http://foo.bar/?baz=qux#quux", "valid": true }, { "description": "an invalid URI", "data": "\\\\WINDOWS\\fileshare", "valid": false }, { "description": "an invalid URI though valid URI reference", "data": "abc", "valid": false } ] }, { "description": "validation of e-mail addresses", "schema": {"format": "email"}, "tests": [ { "description": "a valid e-mail address", "data": "joe.bloggs@example.com", "valid": true }, { "description": "an invalid e-mail address", "data": "2962", "valid": false } ] }, { "description": "validation of IP addresses", "schema": {"format": "ipv4"}, "tests": [ { "description": "a valid IP address", "data": "192.168.0.1", "valid": true }, { "description": "an IP address with too many components", "data": "127.0.0.0.1", "valid": false }, { "description": "an IP address with out-of-range values", "data": "256.256.256.256", "valid": false }, { "description": "an IP address without 4 components", "data": "127.0", "valid": false }, { "description": "an IP address as an integer", "data": "0x7f000001", "valid": false } ] }, { "description": "validation of IPv6 addresses", "schema": {"format": "ipv6"}, "tests": [ { "description": "a valid IPv6 address", "data": "::1", "valid": true }, { "description": "an IPv6 address with out-of-range values", "data": "12345::", "valid": false }, { "description": "an IPv6 address with too many components", "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1", "valid": false }, { "description": "an IPv6 address containing illegal characters", "data": "::laptop", "valid": false } ] }, { "description": "validation of host names", "schema": {"format": "hostname"}, "tests": [ { "description": "a valid host name", "data": "www.example.com", "valid": true }, { "description": "a host name starting with an illegal character", "data": "-a-host-name-that-starts-with--", "valid": false }, { "description": "a host name containing illegal characters", "data": "not_a_valid_host_name", "valid": false }, { "description": "a host name with a component too long", "data": "a-vvvvvvvvvvvvvvvveeeeeeeeeeeeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyyyyy-long-host-name-component", "valid": false } ] } ] mjson-1.4.0/src/test/resources/suite/optional/zeroTerminatedFloats.json000066400000000000000000000006001277350075000264420ustar00rootroot00000000000000[ { "description": "some languages do not distinguish between different types of numeric value", "schema": { "type": "integer" }, "tests": [ { "description": "a float is not an integer even without fractional part", "data": 1.0, "valid": false } ] } ] mjson-1.4.0/src/test/resources/suite/pattern.json000066400000000000000000000011061277350075000221270ustar00rootroot00000000000000[ { "description": "pattern validation", "schema": {"pattern": "^a*$"}, "tests": [ { "description": "a matching pattern is valid", "data": "aaa", "valid": true }, { "description": "a non-matching pattern is invalid", "data": "abc", "valid": false }, { "description": "ignores non-strings", "data": true, "valid": true } ] } ] mjson-1.4.0/src/test/resources/suite/patternProperties.json000066400000000000000000000064451277350075000242170ustar00rootroot00000000000000[ { "description": "patternProperties validates properties matching a regex", "schema": { "patternProperties": { "f.*o": {"type": "integer"} } }, "tests": [ { "description": "a single valid match is valid", "data": {"foo": 1}, "valid": true }, { "description": "multiple valid matches is valid", "data": {"foo": 1, "foooooo" : 2}, "valid": true }, { "description": "a single invalid match is invalid", "data": {"foo": "bar", "fooooo": 2}, "valid": false }, { "description": "multiple invalid matches is invalid", "data": {"foo": "bar", "foooooo" : "baz"}, "valid": false }, { "description": "ignores non-objects", "data": 12, "valid": true } ] }, { "description": "multiple simultaneous patternProperties are validated", "schema": { "patternProperties": { "a*": {"type": "integer"}, "aaa*": {"maximum": 20} } }, "tests": [ { "description": "a single valid match is valid", "data": {"a": 21}, "valid": true }, { "description": "a simultaneous match is valid", "data": {"aaaa": 18}, "valid": true }, { "description": "multiple matches is valid", "data": {"a": 21, "aaaa": 18}, "valid": true }, { "description": "an invalid due to one is invalid", "data": {"a": "bar"}, "valid": false }, { "description": "an invalid due to the other is invalid", "data": {"aaaa": 31}, "valid": false }, { "description": "an invalid due to both is invalid", "data": {"aaa": "foo", "aaaa": 31}, "valid": false } ] }, { "description": "regexes are not anchored by default and are case sensitive", "schema": { "patternProperties": { "[0-9]{2,}": { "type": "boolean" }, "X_": { "type": "string" } } }, "tests": [ { "description": "non recognized members are ignored", "data": { "answer 1": "42" }, "valid": true }, { "description": "recognized members are accounted for", "data": { "a31b": null }, "valid": false }, { "description": "regexes are case sensitive", "data": { "a_x_3": 3 }, "valid": true }, { "description": "regexes are case sensitive, 2", "data": { "a_X_3": 3 }, "valid": false } ] } ] mjson-1.4.0/src/test/resources/suite/properties.json000066400000000000000000000055011277350075000226510ustar00rootroot00000000000000[ { "description": "object properties validation", "schema": { "properties": { "foo": {"type": "integer"}, "bar": {"type": "string"} } }, "tests": [ { "description": "both properties present and valid is valid", "data": {"foo": 1, "bar": "baz"}, "valid": true }, { "description": "one property invalid is invalid", "data": {"foo": 1, "bar": {}}, "valid": false }, { "description": "both properties invalid is invalid", "data": {"foo": [], "bar": {}}, "valid": false }, { "description": "doesn't invalidate other properties", "data": {"quux": []}, "valid": true }, { "description": "ignores non-objects", "data": [], "valid": true } ] }, { "description": "properties, patternProperties, additionalProperties interaction", "schema": { "properties": { "foo": {"type": "array", "maxItems": 3}, "bar": {"type": "array"} }, "patternProperties": {"f.o": {"minItems": 2}}, "additionalProperties": {"type": "integer"} }, "tests": [ { "description": "property validates property", "data": {"foo": [1, 2]}, "valid": true }, { "description": "property invalidates property", "data": {"foo": [1, 2, 3, 4]}, "valid": false }, { "description": "patternProperty invalidates property", "data": {"foo": []}, "valid": false }, { "description": "patternProperty validates nonproperty", "data": {"fxo": [1, 2]}, "valid": true }, { "description": "patternProperty invalidates nonproperty", "data": {"fxo": []}, "valid": false }, { "description": "additionalProperty ignores property", "data": {"bar": []}, "valid": true }, { "description": "additionalProperty validates others", "data": {"quux": 3}, "valid": true }, { "description": "additionalProperty invalidates others", "data": {"quux": "foo"}, "valid": false } ] } ] mjson-1.4.0/src/test/resources/suite/ref.json000066400000000000000000000074771277350075000212470ustar00rootroot00000000000000[ { "description": "root pointer ref", "schema": { "properties": { "foo": {"$ref": "#"} }, "additionalProperties": false }, "tests": [ { "description": "match", "data": {"foo": false}, "valid": true }, { "description": "recursive match", "data": {"foo": {"foo": false}}, "valid": true }, { "description": "mismatch", "data": {"bar": false}, "valid": false }, { "description": "recursive mismatch", "data": {"foo": {"bar": false}}, "valid": false } ] }, { "description": "relative pointer ref to object", "schema": { "properties": { "foo": {"type": "integer"}, "bar": {"$ref": "#/properties/foo"} } }, "tests": [ { "description": "match", "data": {"bar": 3}, "valid": true }, { "description": "mismatch", "data": {"bar": true}, "valid": false } ] }, { "description": "relative pointer ref to array", "schema": { "items": [ {"type": "integer"}, {"$ref": "#/items/0"} ] }, "tests": [ { "description": "match array", "data": [1, 2], "valid": true }, { "description": "mismatch array", "data": [1, "foo"], "valid": false } ] }, { "description": "escaped pointer ref", "schema": { "tilda~field": {"type": "integer"}, "slash/field": {"type": "integer"}, "percent%field": {"type": "integer"}, "properties": { "tilda": {"$ref": "#/tilda~0field"}, "slash": {"$ref": "#/slash~1field"}, "percent": {"$ref": "#/percent%25field"} } }, "tests": [ { "description": "slash", "data": {"slash": "aoeu"}, "valid": false }, { "description": "tilda", "data": {"tilda": "aoeu"}, "valid": false }, { "description": "percent", "data": {"percent": "aoeu"}, "valid": false } ] }, { "description": "nested refs", "schema": { "definitions": { "a": {"type": "integer"}, "b": {"$ref": "#/definitions/a"}, "c": {"$ref": "#/definitions/b"} }, "$ref": "#/definitions/c" }, "tests": [ { "description": "nested ref valid", "data": 5, "valid": true }, { "description": "nested ref invalid", "data": "a", "valid": false } ] }, { "description": "remote ref, containing refs itself", "schema": {"$ref": "http://json-schema.org/draft-04/schema#"}, "tests": [ { "description": "remote ref valid", "data": {"minLength": 1}, "valid": true }, { "description": "remote ref invalid", "data": {"minLength": -1}, "valid": false } ] } ] mjson-1.4.0/src/test/resources/suite/refRemote.json000066400000000000000000000042461277350075000224120ustar00rootroot00000000000000[ { "description": "remote ref", "schema": {"$ref": "https://raw.githubusercontent.com/json-schema/JSON-Schema-Test-Suite/develop/remotes/integer.json"}, "tests": [ { "description": "remote ref valid", "data": 1, "valid": true }, { "description": "remote ref invalid", "data": "a", "valid": false } ] }, { "description": "fragment within remote ref", "schema": {"$ref": "https://raw.githubusercontent.com/json-schema/JSON-Schema-Test-Suite/develop/remotes/subSchemas.json#/integer"}, "tests": [ { "description": "remote fragment valid", "data": 1, "valid": true }, { "description": "remote fragment invalid", "data": "a", "valid": false } ] }, { "description": "ref within remote ref", "schema": { "$ref": "https://raw.githubusercontent.com/json-schema/JSON-Schema-Test-Suite/develop/remotes/subSchemas.json#/refToInteger" }, "tests": [ { "description": "ref within ref valid", "data": 1, "valid": true }, { "description": "ref within ref invalid", "data": "a", "valid": false } ] }, { "description": "change resolution scope", "schema": { "id": "https://raw.githubusercontent.com/json-schema/JSON-Schema-Test-Suite/develop/remotes/", "items": { "id": "folder/", "items": {"$ref": "folderInteger.json"} } }, "tests": [ { "description": "changed scope ref valid", "data": [[1]], "valid": true }, { "description": "changed scope ref invalid", "data": [["a"]], "valid": false } ] } ] mjson-1.4.0/src/test/resources/suite/required.json000066400000000000000000000016331277350075000222770ustar00rootroot00000000000000[ { "description": "required validation", "schema": { "properties": { "foo": {}, "bar": {} }, "required": ["foo"] }, "tests": [ { "description": "present required property is valid", "data": {"foo": 1}, "valid": true }, { "description": "non-present required property is invalid", "data": {"bar": 1}, "valid": false } ] }, { "description": "required default validation", "schema": { "properties": { "foo": {} } }, "tests": [ { "description": "not required by default", "data": {}, "valid": true } ] } ] mjson-1.4.0/src/test/resources/suite/type.json000066400000000000000000000221321277350075000214350ustar00rootroot00000000000000[ { "description": "integer type matches integers", "schema": {"type": "integer"}, "tests": [ { "description": "an integer is an integer", "data": 1, "valid": true }, { "description": "a float is not an integer", "data": 1.1, "valid": false }, { "description": "a string is not an integer", "data": "foo", "valid": false }, { "description": "an object is not an integer", "data": {}, "valid": false }, { "description": "an array is not an integer", "data": [], "valid": false }, { "description": "a boolean is not an integer", "data": true, "valid": false }, { "description": "null is not an integer", "data": null, "valid": false } ] }, { "description": "number type matches numbers", "schema": {"type": "number"}, "tests": [ { "description": "an integer is a number", "data": 1, "valid": true }, { "description": "a float is a number", "data": 1.1, "valid": true }, { "description": "a string is not a number", "data": "foo", "valid": false }, { "description": "an object is not a number", "data": {}, "valid": false }, { "description": "an array is not a number", "data": [], "valid": false }, { "description": "a boolean is not a number", "data": true, "valid": false }, { "description": "null is not a number", "data": null, "valid": false } ] }, { "description": "string type matches strings", "schema": {"type": "string"}, "tests": [ { "description": "1 is not a string", "data": 1, "valid": false }, { "description": "a float is not a string", "data": 1.1, "valid": false }, { "description": "a string is a string", "data": "foo", "valid": true }, { "description": "an object is not a string", "data": {}, "valid": false }, { "description": "an array is not a string", "data": [], "valid": false }, { "description": "a boolean is not a string", "data": true, "valid": false }, { "description": "null is not a string", "data": null, "valid": false } ] }, { "description": "object type matches objects", "schema": {"type": "object"}, "tests": [ { "description": "an integer is not an object", "data": 1, "valid": false }, { "description": "a float is not an object", "data": 1.1, "valid": false }, { "description": "a string is not an object", "data": "foo", "valid": false }, { "description": "an object is an object", "data": {}, "valid": true }, { "description": "an array is not an object", "data": [], "valid": false }, { "description": "a boolean is not an object", "data": true, "valid": false }, { "description": "null is not an object", "data": null, "valid": false } ] }, { "description": "array type matches arrays", "schema": {"type": "array"}, "tests": [ { "description": "an integer is not an array", "data": 1, "valid": false }, { "description": "a float is not an array", "data": 1.1, "valid": false }, { "description": "a string is not an array", "data": "foo", "valid": false }, { "description": "an object is not an array", "data": {}, "valid": false }, { "description": "an array is not an array", "data": [], "valid": true }, { "description": "a boolean is not an array", "data": true, "valid": false }, { "description": "null is not an array", "data": null, "valid": false } ] }, { "description": "boolean type matches booleans", "schema": {"type": "boolean"}, "tests": [ { "description": "an integer is not a boolean", "data": 1, "valid": false }, { "description": "a float is not a boolean", "data": 1.1, "valid": false }, { "description": "a string is not a boolean", "data": "foo", "valid": false }, { "description": "an object is not a boolean", "data": {}, "valid": false }, { "description": "an array is not a boolean", "data": [], "valid": false }, { "description": "a boolean is not a boolean", "data": true, "valid": true }, { "description": "null is not a boolean", "data": null, "valid": false } ] }, { "description": "null type matches only the null object", "schema": {"type": "null"}, "tests": [ { "description": "an integer is not null", "data": 1, "valid": false }, { "description": "a float is not null", "data": 1.1, "valid": false }, { "description": "a string is not null", "data": "foo", "valid": false }, { "description": "an object is not null", "data": {}, "valid": false }, { "description": "an array is not null", "data": [], "valid": false }, { "description": "a boolean is not null", "data": true, "valid": false }, { "description": "null is null", "data": null, "valid": true } ] }, { "description": "multiple types can be specified in an array", "schema": {"type": ["integer", "string"]}, "tests": [ { "description": "an integer is valid", "data": 1, "valid": true }, { "description": "a string is valid", "data": "foo", "valid": true }, { "description": "a float is invalid", "data": 1.1, "valid": false }, { "description": "an object is invalid", "data": {}, "valid": false }, { "description": "an array is invalid", "data": [], "valid": false }, { "description": "a boolean is invalid", "data": true, "valid": false }, { "description": "null is invalid", "data": null, "valid": false } ] } ] mjson-1.4.0/src/test/resources/suite/uniqueItems.json000066400000000000000000000050651277350075000227720ustar00rootroot00000000000000[ { "description": "uniqueItems validation", "schema": {"uniqueItems": true}, "tests": [ { "description": "unique array of integers is valid", "data": [1, 2], "valid": true }, { "description": "non-unique array of integers is invalid", "data": [1, 1], "valid": false }, { "description": "numbers are unique if mathematically unequal", "data": [1.0, 1.00, 1], "valid": false }, { "description": "unique array of objects is valid", "data": [{"foo": "bar"}, {"foo": "baz"}], "valid": true }, { "description": "non-unique array of objects is invalid", "data": [{"foo": "bar"}, {"foo": "bar"}], "valid": false }, { "description": "unique array of nested objects is valid", "data": [ {"foo": {"bar" : {"baz" : true}}}, {"foo": {"bar" : {"baz" : false}}} ], "valid": true }, { "description": "non-unique array of nested objects is invalid", "data": [ {"foo": {"bar" : {"baz" : true}}}, {"foo": {"bar" : {"baz" : true}}} ], "valid": false }, { "description": "unique array of arrays is valid", "data": [["foo"], ["bar"]], "valid": true }, { "description": "non-unique array of arrays is invalid", "data": [["foo"], ["foo"]], "valid": false }, { "description": "1 and true are unique", "data": [1, true], "valid": true }, { "description": "0 and false are unique", "data": [0, false], "valid": true }, { "description": "unique heterogeneous types are valid", "data": [{}, [1], true, null, 1], "valid": true }, { "description": "non-unique heterogeneous types are invalid", "data": [{}, [1], true, null, {}, 1], "valid": false } ] } ]