Merge pull request #6434 from smowton/smowton/admin/jodd-unsafe-deserialization

Java: Unsafe deserialization: add support for Jodd JSON library
This commit is contained in:
Chris Smowton
2021-08-18 17:26:02 +01:00
committed by GitHub
12 changed files with 1294 additions and 2 deletions

View File

@@ -0,0 +1,2 @@
lgtm,codescanning
* The "Deserialization of user-controlled data" (`java/unsafe-deserialization`) query now recognizes deserialization using the `Jodd JSON` library.

View File

@@ -15,7 +15,7 @@ may have unforeseen effects, such as the execution of arbitrary code.
<p>
There are many different serialization frameworks. This query currently
supports Kryo, XmlDecoder, XStream, SnakeYaml, JYaml, JsonIO, YAMLBeans, HessianBurlap, Castor, Burlap,
Jackson, Jabsorb and Java IO serialization through
Jackson, Jabsorb, Jodd JSON and Java IO serialization through
<code>ObjectInputStream</code>/<code>ObjectOutputStream</code>.
</p>
</overview>
@@ -105,6 +105,10 @@ Blog posts by the developer of Jackson libraries:
Jabsorb documentation on deserialization:
<a href="https://github.com/Servoy/jabsorb/blob/master/src/org/jabsorb/">Jabsorb JSON Serializer</a>.
</li>
<li>
Jodd JSON documentation on deserialization:
<a href="https://json.jodd.org/parser">JoddJson Parser</a>.
</li>
</references>
</qhelp>

View File

@@ -85,6 +85,7 @@ private module Frameworks {
private import semmle.code.java.frameworks.jackson.JacksonSerializability
private import semmle.code.java.frameworks.JavaxJson
private import semmle.code.java.frameworks.JaxWS
private import semmle.code.java.frameworks.JoddJson
private import semmle.code.java.frameworks.JsonJava
private import semmle.code.java.frameworks.Optional
private import semmle.code.java.frameworks.spring.SpringCache

View File

@@ -0,0 +1,68 @@
/**
* Provides classes and predicates for working with the Jodd JSON framework.
*/
import java
private import semmle.code.java.dataflow.ExternalFlow
/** The class `jodd.json.Parser`. */
class JoddJsonParser extends RefType {
JoddJsonParser() { this.hasQualifiedName("jodd.json", "JsonParser") }
}
/** A `JsonParser.parse*` deserialization method. */
class JoddJsonParseMethod extends Method {
JoddJsonParseMethod() {
this.getDeclaringType() instanceof JoddJsonParser and
this.getName().matches("parse%")
}
}
/** The `JsonParser.setClassMetadataName` method. */
class SetClassMetadataNameMethod extends Method {
SetClassMetadataNameMethod() {
this.getDeclaringType() instanceof JoddJsonParser and
this.hasName("setClassMetadataName")
}
}
/** The `JsonParser.withClassMetadata` method. */
class WithClassMetadataMethod extends Method {
WithClassMetadataMethod() {
this.getDeclaringType() instanceof JoddJsonParser and
this.hasName("withClassMetadata")
}
}
/** The `JsonParser.allowClass` method. */
class AllowClassMethod extends Method {
AllowClassMethod() {
this.getDeclaringType() instanceof JoddJsonParser and
this.hasName("allowClass")
}
}
/**
* A partial model of jodd.json.JsonParser noting fluent methods.
*
* This means that DataFlow::localFlow and similar methods are aware
* that the result of (e.g.) JsonParser.allowClass is an alias of the
* qualifier.
*/
private class JsonParserFluentMethods extends SummaryModelCsv {
override predicate row(string s) {
s =
[
"jodd.json;JsonParser;false;allowAllClasses;;;Argument[-1];ReturnValue;value",
"jodd.json;JsonParser;false;allowClass;;;Argument[-1];ReturnValue;value",
"jodd.json;JsonParser;false;lazy;;;Argument[-1];ReturnValue;value",
"jodd.json;JsonParser;false;looseMode;;;Argument[-1];ReturnValue;value",
"jodd.json;JsonParser;false;map;;;Argument[-1];ReturnValue;value",
"jodd.json;JsonParser;false;setClassMetadataName;;;Argument[-1];ReturnValue;value",
"jodd.json;JsonParser;false;strictTypes;;;Argument[-1];ReturnValue;value",
"jodd.json;JsonParser;false;useAltPaths;;;Argument[-1];ReturnValue;value",
"jodd.json;JsonParser;false;withClassMetadata;;;Argument[-1];ReturnValue;value",
"jodd.json;JsonParser;false;withValueConverter;;;Argument[-1];ReturnValue;value"
]
}
}

View File

@@ -15,6 +15,7 @@ private import semmle.code.java.frameworks.HessianBurlap
private import semmle.code.java.frameworks.Castor
private import semmle.code.java.frameworks.Jackson
private import semmle.code.java.frameworks.Jabsorb
private import semmle.code.java.frameworks.JoddJson
private import semmle.code.java.frameworks.apache.Lang
private import semmle.code.java.Reflection
@@ -192,6 +193,16 @@ predicate unsafeDeserialization(MethodAccess ma, Expr sink) {
or
m instanceof JabsorbFromJsonMethod and
sink = ma.getArgument(0)
or
m instanceof JoddJsonParseMethod and
sink = ma.getArgument(0) and
(
// User controls the target type for deserialization
any(UnsafeTypeConfig c).hasFlowToExpr(ma.getArgument(1))
or
// jodd.json.JsonParser may be configured for unrestricted deserialization to user-specified types
joddJsonParserConfiguredUnsafely(ma.getQualifier())
)
)
}
@@ -248,6 +259,17 @@ class UnsafeDeserializationConfig extends TaintTracking::Configuration {
ma.getArgument(0) = node.asExpr() and
exists(SafeJsonIoConfig sji | sji.hasFlowToExpr(ma.getArgument(1)))
)
or
exists(MethodAccess ma |
// Sanitize the input to jodd.json.JsonParser.parse et al whenever it appears
// to be called with an explicit class argument limiting those types that can
// be instantiated during deserialization.
ma.getMethod() instanceof JoddJsonParseMethod and
ma.getArgument(1).getType() instanceof TypeClass and
not ma.getArgument(1) instanceof NullLiteral and
not ma.getArgument(1).getType().getName() = ["Class<Object>", "Class<?>"] and
node.asExpr() = ma.getAnArgument()
)
}
}
@@ -295,6 +317,8 @@ class UnsafeTypeConfig extends TaintTracking2::Configuration {
ma.getMethod() instanceof ObjectMapperReadMethod
or
ma.getMethod() instanceof JabsorbUnmarshallMethod
or
ma.getMethod() instanceof JoddJsonParseMethod
) and
// Note `JacksonTypeDescriptorType` includes plain old `java.lang.Class`
arg.getType() instanceof JacksonTypeDescriptorType and
@@ -356,3 +380,85 @@ class SafeObjectMapperConfig extends DataFlow2::Configuration {
)
}
}
/**
* A method that configures Jodd's JsonParser, either enabling dangerous deserialization to
* arbitrary Java types or restricting the types that can be instantiated.
*/
private class JoddJsonParserConfigurationMethodQualifier extends DataFlow::ExprNode {
JoddJsonParserConfigurationMethodQualifier() {
exists(MethodAccess ma, Method m | ma.getQualifier() = this.asExpr() and m = ma.getMethod() |
m instanceof WithClassMetadataMethod
or
m instanceof SetClassMetadataNameMethod
or
m instanceof AllowClassMethod
)
}
}
/**
* Configuration tracking flow from methods that configure `jodd.json.JsonParser`'s class
* instantiation feature to a `.parse` call on the same parser.
*/
private class JoddJsonParserConfigurationMethodConfig extends DataFlow2::Configuration {
JoddJsonParserConfigurationMethodConfig() {
this = "UnsafeDeserialization::JoddJsonParserConfigurationMethodConfig"
}
override predicate isSource(DataFlow::Node src) {
src instanceof JoddJsonParserConfigurationMethodQualifier
}
override predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma |
ma.getMethod() instanceof JoddJsonParseMethod and
sink.asExpr() = ma.getQualifier() // The class type argument
)
}
}
/**
* Gets the qualifier to a method call that configures a `jodd.json.JsonParser` instance unsafely.
*
* Such a parser may instantiate an arbtirary type when deserializing untrusted data.
*/
private DataFlow::Node getAnUnsafelyConfiguredParser() {
exists(MethodAccess ma | result.asExpr() = ma.getQualifier() |
ma.getMethod() instanceof WithClassMetadataMethod and
ma.getArgument(0).(CompileTimeConstantExpr).getBooleanValue() = true
or
ma.getMethod() instanceof SetClassMetadataNameMethod and
not ma.getArgument(0) instanceof NullLiteral
)
}
/**
* Gets the qualifier to a method call that configures a `jodd.json.JsonParser` instance safely.
*
* Such a parser will not instantiate an arbtirary type when deserializing untrusted data.
*/
private DataFlow::Node getASafelyConfiguredParser() {
exists(MethodAccess ma | result.asExpr() = ma.getQualifier() |
ma.getMethod() instanceof WithClassMetadataMethod and
ma.getArgument(0).(CompileTimeConstantExpr).getBooleanValue() = false
or
ma.getMethod() instanceof SetClassMetadataNameMethod and
ma.getArgument(0) instanceof NullLiteral
or
ma.getMethod() instanceof AllowClassMethod
)
}
/**
* Holds if `parseMethodQualifierExpr` is a `jodd.json.JsonParser` instance that is configured unsafely
* and which never appears to be configured safely.
*/
private predicate joddJsonParserConfiguredUnsafely(Expr parserExpr) {
exists(DataFlow::Node parser, JoddJsonParserConfigurationMethodConfig config |
parser.asExpr() = parserExpr
|
config.hasFlow(getAnUnsafelyConfiguredParser(), parser) and
not config.hasFlow(getASafelyConfiguredParser(), parser)
)
}

View File

@@ -0,0 +1,102 @@
import java.io.IOException;
import java.io.Reader;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jodd.json.JsonParser;
import com.example.User;
import com.thirdparty.Person;
public class JoddJsonServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
// GOOD: class type specified (despite a dangerous configuration)
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String json = req.getParameter("json");
String clazz = req.getParameter("class");
JsonParser parser = new JsonParser();
parser.setClassMetadataName("class");
Person person = parser.parse(json, Person.class);
}
@Override
// BAD: dangerously configured parser with no class restriction passed to `parse`,
// using a few different possible call sequences.
public void doHead(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String json = req.getParameter("json");
String clazz = req.getParameter("class");
int callOrder;
try {
callOrder = Integer.parseInt(req.getParameter("callOrder"));
}
catch(NumberFormatException e) {
throw new RuntimeException(e);
}
JsonParser parser = new JsonParser();
if(callOrder == 0) {
parser.setClassMetadataName("class");
User obj = parser.parse(json, null); // $unsafeDeserialization
} else if(callOrder == 1) {
parser.setClassMetadataName("class").parse(json, null); // $unsafeDeserialization
} else if(callOrder == 2) {
parser.setClassMetadataName("class").lazy(true).parse(json, null); // $unsafeDeserialization
} else if(callOrder == 3) {
parser.withClassMetadata(true).lazy(true).parse(json, null); // $unsafeDeserialization
}
}
@Override
// BAD: allow class name to be controlled by remote source
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String json = req.getParameter("json");
String clazz = req.getParameter("class");
try {
JsonParser parser = new JsonParser();
Object obj = parser.parse(json, Class.forName(clazz)); // $unsafeDeserialization
} catch (ClassNotFoundException cne) {
throw new IOException(cne.getMessage());
}
}
@Override
// GOOD: dangerously configured parser is ameliorated by setting a list of allowed classes, using various call orders,
// or by explicitly disabling the class metadata option.
public void doPut(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String json = req.getParameter("json");
String clazz = req.getParameter("class");
int callOrder;
try {
callOrder = Integer.parseInt(req.getParameter("callOrder"));
}
catch(NumberFormatException e) {
throw new RuntimeException(e);
}
JsonParser parser = new JsonParser();
if(callOrder == 0) {
parser.setClassMetadataName("class");
parser.allowClass("example.Class");
User obj = parser.parse(json, null);
} else if(callOrder == 1) {
parser.allowClass("example.Class");
parser.setClassMetadataName("class");
User obj = parser.parse(json, null);
} else if(callOrder == 2) {
parser.setClassMetadataName("class").allowClass("example.Class").parse(json, null);
} else if(callOrder == 3) {
parser.allowClass("example.Class").setClassMetadataName("class").parse(json, null);
} else if(callOrder == 4) {
parser.setClassMetadataName("class").withClassMetadata(false).parse(json, null);
} else if(callOrder == 5) {
parser.withClassMetadata(true).setClassMetadataName(null).parse(json, null);
}
}
}

View File

@@ -1 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/snakeyaml-1.21:${testdir}/../../../stubs/xstream-1.4.10:${testdir}/../../../stubs/kryo-4.0.2:${testdir}/../../../stubs/jsr311-api-1.1.1:${testdir}/../../../stubs/fastjson-1.2.74:${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/servlet-api-2.4:${testdir}/../../../stubs/jyaml-1.3:${testdir}/../../../stubs/json-io-4.10.0:${testdir}/../../../stubs/yamlbeans-1.09:${testdir}/../../../stubs/hessian-4.0.38:${testdir}/../../../stubs/castor-1.4.1:${testdir}/../../../stubs/jackson-databind-2.12:${testdir}/../../../stubs/jackson-core-2.12:${testdir}/../../../stubs/jabsorb-1.3.2:${testdir}/../../../stubs/json-java-20210307
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/snakeyaml-1.21:${testdir}/../../../stubs/xstream-1.4.10:${testdir}/../../../stubs/kryo-4.0.2:${testdir}/../../../stubs/jsr311-api-1.1.1:${testdir}/../../../stubs/fastjson-1.2.74:${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/servlet-api-2.4:${testdir}/../../../stubs/jyaml-1.3:${testdir}/../../../stubs/json-io-4.10.0:${testdir}/../../../stubs/yamlbeans-1.09:${testdir}/../../../stubs/hessian-4.0.38:${testdir}/../../../stubs/castor-1.4.1:${testdir}/../../../stubs/jackson-databind-2.12:${testdir}/../../../stubs/jackson-core-2.12:${testdir}/../../../stubs/jabsorb-1.3.2:${testdir}/../../../stubs/json-java-20210307:${testdir}/../../../stubs/joddjson-6.0.3

View File

@@ -0,0 +1,293 @@
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
package jodd.json;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Representation of JSON array.
* @see JsonObject
*/
public class JsonArray implements Iterable<Object> {
/**
* Creates an empty instance.
*/
public JsonArray() {
}
/**
* Creates an instance from a List. The List is not copied.
*/
public JsonArray(final List list) {
}
// ---------------------------------------------------------------- get
/**
* Returns the string at position {@code pos} in the array.
*/
public String getString(final int pos) {
return null;
}
/**
* Returns the integer at position {@code pos} in the array.
*/
public Integer getInteger(final int pos) {
return null;
}
/**
* Returns the long at position {@code pos} in the array.
*/
public Long getLong(final int pos) {
return null;
}
/**
* Returns the double at position {@code pos} in the array.
*/
public Double getDouble(final int pos) {
return null;
}
/**
* Returns the Float at position {@code pos} in the array.
*/
public Float getFloat(final int pos) {
return null;
}
/**
* Returns the boolean at position {@code pos} in the array.
*/
public Boolean getBoolean(final int pos) {
return null;
}
/**
* Returns the JsonObject at position {@code pos} in the array.
*/
public JsonObject getJsonObject(final int pos) {
return null;
}
/**
* Returns the JsonArray at position {@code pos} in the array.
*/
public JsonArray getJsonArray(final int pos) {
return null;
}
/**
* Returns the byte[] at position {@code pos} in the array.
* <p>
* JSON itself has no notion of a binary, so this method assumes there is a String value and
* it contains a Base64 encoded binary, which it decodes if found and returns.
*/
public byte[] getBinary(final int pos) {
return null;
}
/**
* Returns the object value at position {@code pos} in the array.
*/
public Object getValue(final int pos) {
return null;
}
/**
* Returns {@code true} if there is a {@code null} value at given index.
*/
public boolean hasNull(final int pos) {
return false;
}
/**
* Adds an enum to the JSON array.
* <p>
* JSON has no concept of encoding Enums, so the Enum will be converted to a String using the {@link java.lang.Enum#name}
* method and the value added as a String.
*/
public JsonArray add(final Enum value) {
return null;
}
/**
* Adds a {@code CharSequence} to the JSON array.
*/
public JsonArray add(final CharSequence value) {
return null;
}
/**
* Adds a string to the JSON array.
*/
public JsonArray add(final String value) {
return null;
}
/**
* Adds an integer to the JSON array.
*/
public JsonArray add(final Integer value) {
return null;
}
/**
* Adds a long to the JSON array.
*/
public JsonArray add(final Long value) {
return null;
}
/**
* Adds a double to the JSON array.
*/
public JsonArray add(final Double value) {
return null;
}
/**
* Adds a float to the JSON array.
*/
public JsonArray add(final Float value) {
return null;
}
/**
* Adds a boolean to the JSON array.
*/
public JsonArray add(final Boolean value) {
return null;
}
/**
* Adds a {@code null} value to the JSON array.
*/
public JsonArray addNull() {
return null;
}
/**
* Adds a JSON object to the JSON array.
*/
public JsonArray add(final JsonObject value) {
return null;
}
/**
* Adds another JSON array to the JSON array.
*/
public JsonArray add(final JsonArray value) {
return null;
}
/**
* Adds a binary value to the JSON array.
* <p>
* JSON has no notion of binary so the binary will be base64 encoded to a String, and the String added.
*/
public JsonArray add(final byte[] value) {
return null;
}
/**
* Adds an object to the JSON array.
*/
public JsonArray add(Object value) {
return null;
}
/**
* Appends all of the elements in the specified array to the end of this JSON array.
*/
public JsonArray addAll(final JsonArray array) {
return null;
}
// ---------------------------------------------------------------- misc
/**
* Returns {@code true} if given value exist.
*/
public boolean contains(final Object value) {
return false;
}
/**
* Removes the specified value from the JSON array.
*/
public boolean remove(final Object value) {
return false;
}
/**
* Removes the value at the specified position in the JSON array.
*/
public Object remove(final int pos) {
return null;
}
/**
* Returns the number of values in this JSON array.
*/
public int size() {
return -1;
}
/**
* Returns {@code true} if JSON array is empty.
*/
public boolean isEmpty() {
return false;
}
/**
* Returns the underlying list.
*/
public List<Object> list() {
return null;
}
/**
* Removes all entries from the JSON array.
*/
public JsonArray clear() {
return null;
}
/**
* Returns an iterator over the values in the JSON array.
*/
@Override
public Iterator<Object> iterator() {
return null;
}
}

View File

@@ -0,0 +1,385 @@
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
package jodd.json;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Representation of JSON object.
* @see JsonArray
*/
public class JsonObject implements Iterable<Map.Entry<String, Object>> {
/**
* Create a new, empty instance.
*/
public JsonObject() {
}
/**
* Create an instance from a Map. The Map is not copied.
*/
public JsonObject(final Map<String, Object> map) {
}
/**
* Returns the string value with the specified key.
*/
public String getString(final String key) {
return null;
}
/**
* returns the integer value with the specified key.
*/
public Integer getInteger(final String key) {
return null;
}
/**
* Returns the long value with the specified key.
*/
public Long getLong(final String key) {
return null;
}
/**
* Returns the double value with the specified key.
*/
public Double getDouble(final String key) {
return null;
}
/**
* Returns the float value with the specified key.
*/
public Float getFloat(final String key) {
return null;
}
/**
* Returns the boolean value with the specified key.
*/
public Boolean getBoolean(final String key) {
return false;
}
/**
* Returns the {@code JsonObject} value with the specified key.
*/
public JsonObject getJsonObject(final String key) {
return null;
}
/**
* Returns the {@link JsonArray} value with the specified key
*/
public JsonArray getJsonArray(final String key) {
return null;
}
/**
* Returns the binary value with the specified key.
* <p>
* JSON itself has no notion of a binary. This extension complies to the RFC-7493.
* THe byte array is Base64 encoded binary.
*/
public byte[] getBinary(final String key) {
return null;
}
/**
* Returns the value with the specified key, as an object.
*/
@SuppressWarnings("unchecked")
public <T> T getValue(final String key) {
return null;
}
/**
* Like {@link #getString(String)} but specifies a default value to return if there is no entry.
*/
public String getString(final String key, final String def) {
return null;
}
/**
* Like {@link #getInteger(String)} but specifies a default value to return if there is no entry.
*/
public Integer getInteger(final String key, final Integer def) {
return null;
}
/**
* Like {@link #getLong(String)} but specifies a default value to return if there is no entry.
*/
public Long getLong(final String key, final Long def) {
return null;
}
/**
* Like {@link #getDouble(String)} but specifies a default value to return if there is no entry.
*/
public Double getDouble(final String key, final Double def) {
return null;
}
/**
* Like {@link #getFloat(String)} but specifies a default value to return if there is no entry.
*/
public Float getFloat(final String key, final Float def) {
return null;
}
/**
* Like {@link #getBoolean(String)} but specifies a default value to return if there is no entry.
*/
public Boolean getBoolean(final String key, final Boolean def) {
return null;
}
/**
* Like {@link #getJsonObject(String)} but specifies a default value to return if there is no entry.
*/
public JsonObject getJsonObject(final String key, final JsonObject def) {
return null;
}
/**
* Like {@link #getJsonArray(String)} but specifies a default value to return if there is no entry.
*/
public JsonArray getJsonArray(final String key, final JsonArray def) {
return null;
}
/**
* Like {@link #getBinary(String)} but specifies a default value to return if there is no entry.
*/
public byte[] getBinary(final String key, final byte[] def) {
return null;
}
/**
* Like {@link #getValue(String)} but specifies a default value to return if there is no entry.
*/
public <T> T getValue(final String key, final T def) {
return null;
}
/**
* Returns {@code true} if the JSON object contain the specified key.
*/
public boolean containsKey(final String key) {
return false;
}
/**
* Return the set of field names in the JSON objects.
*/
public Set<String> fieldNames() {
return null;
}
// ---------------------------------------------------------------- put
/**
* Puts an Enum into the JSON object with the specified key.
* <p>
* JSON has no concept of encoding Enums, so the Enum will be converted to a String using the {@code java.lang.Enum#name}
* method and the value put as a String.
*/
public JsonObject put(final String key, final Enum value) {
return null;
}
/**
* Puts an {@code CharSequence} into the JSON object with the specified key.
*/
public JsonObject put(final String key, final CharSequence value) {
return null;
}
/**
* Puts a string into the JSON object with the specified key.
*/
public JsonObject put(final String key, final String value) {
return null;
}
/**
* Puts an integer into the JSON object with the specified key.
*/
public JsonObject put(final String key, final Integer value) {
return null;
}
/**
* Puts a long into the JSON object with the specified key.
*/
public JsonObject put(final String key, final Long value) {
return null;
}
/**
* Puts a double into the JSON object with the specified key.
*/
public JsonObject put(final String key, final Double value) {
return null;
}
/**
* Puts a float into the JSON object with the specified key.
*/
public JsonObject put(final String key, final Float value) {
return null;
}
/**
* Puts a boolean into the JSON object with the specified key.
*/
public JsonObject put(final String key, final Boolean value) {
return null;
}
/**
* Puts a {@code null} value into the JSON object with the specified key.
*/
public JsonObject putNull(final String key) {
return null;
}
/**
* Puts another JSON object into the JSON object with the specified key.
*/
public JsonObject put(final String key, final JsonObject value) {
return null;
}
/**
* Puts a {@link JsonArray} into the JSON object with the specified key.
*/
public JsonObject put(final String key, final JsonArray value) {
return null;
}
/**
* Puts a {@code byte[]} into the JSON object with the specified key.
* <p>
* Follows JSON extension RFC7493, where binary will first be Base64
* encoded before being put as a String.
*/
public JsonObject put(final String key, final byte[] value) {
return null;
}
/**
* Puts an object into the JSON object with the specified key.
*/
public JsonObject put(final String key, Object value) {
return null;
}
@SuppressWarnings("StatementWithEmptyBody")
static Object resolveValue(Object value) {
return null;
}
/**
* Removes an entry from this object.
*/
public Object remove(final String key) {
return null;
}
/**
* Merges in another JSON object.
* <p>
* This is the equivalent of putting all the entries of the other JSON object into this object. This is not a deep
* merge, entries containing (sub) JSON objects will be replaced entirely.
*/
public JsonObject mergeIn(final JsonObject other) {
return null;
}
/**
* Merges in another JSON object.
* A deep merge (recursive) matches (sub) JSON objects in the existing tree and replaces all
* matching entries. JsonArrays are treated like any other entry, i.e. replaced entirely.
*/
public JsonObject mergeInDeep(final JsonObject other) {
return null;
}
/**
* Merges in another JSON object.
* The merge is deep (recursive) to the specified level. If depth is 0, no merge is performed,
* if depth is greater than the depth of one of the objects, a full deep merge is performed.
*/
@SuppressWarnings("unchecked")
public JsonObject mergeIn(final JsonObject other, final int depth) {
return null;
}
/**
* Returns the underlying {@code Map} as is.
*/
public Map<String, Object> map() {
return null;
}
/**
* Returns an iterator of the entries in the JSON object.
*/
@Override
public Iterator<Map.Entry<String, Object>> iterator() {
return null;
}
/**
* Returns the number of entries in the JSON object.
*/
public int size() {
return -1;
}
/**
* Removes all the entries in this JSON object.
*/
public JsonObject clear() {
return null;
}
/**
* Returns {@code true} if JSON object is empty.
*/
public boolean isEmpty() {
return false;
}
}

View File

@@ -0,0 +1,218 @@
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
package jodd.json;
import java.util.List;
import java.util.Map;
/**
* Simple, developer-friendly JSON parser. It focuses on easy usage
* and type mappings. Uses Jodd's type converters, so it is natural
* companion for Jodd projects.
* <p>
* This JSON parser also works in {@link #lazy(boolean)} mode. This
* mode is for top performance usage: parsing is done very, very lazy.
* While you can use all the mappings and other tools, for best performance
* the lazy mode should be used only with maps and lists (no special mappings).
* Also, the performance has it's price: more memory consumption, because the
* original input is hold until the result is in use.
* <p>
* See: http://www.ietf.org/rfc/rfc4627.txt
*/
public class JsonParser extends JsonParserBase {
/**
* Static ctor.
*/
public static JsonParser create() {
return null;
}
/**
* Creates a lazy implementation of the JSON parser.
*/
public static JsonParser createLazyOne() {
return null;
}
public JsonParser() {
super(false);
}
/**
* Enables 'loose' mode for parsing. When 'loose' mode is enabled,
* JSON parsers swallows also invalid JSONs:
* <ul>
* <li>invalid escape character sequence is simply added to the output</li>
* <li>strings can be quoted with single-quotes</li>
* <li>strings can be unquoted, but may not contain escapes</li>
* </ul>
*/
public JsonParser looseMode(final boolean looseMode) {
return null;
}
/**
* Defines if type conversion is strict. If not, all exceptions will be
* caught and replaced with {@code null}.
*/
public JsonParser strictTypes(final boolean strictTypes) {
return null;
}
/**
* Defines how JSON parser works. In non-lazy mode, the whole JSON is parsed as it is.
* In the lazy mode, not everything is parsed, but some things are left lazy.
* This way we gain performance, especially on partial usage of the whole JSON.
* However, be aware that parser holds the input memory until the returned
* objects are disposed.
*/
public JsonParser lazy(final boolean lazy) {
return null;
}
/**
* Maps a class to JSONs root.
*/
public JsonParser map(final Class target) {
return null;
}
/**
* Maps a class to given path. For arrays, append <code>values</code>
* to the path to specify component type (if not specified by
* generics).
*/
public JsonParser map(final String path, final Class target) {
return null;
}
/**
* Replaces type with mapped type for current path.
*/
protected Class replaceWithMappedTypeForPath(final Class target) {
return null;
}
/**
* Sets local class meta-data name.
* <p>
* Note that by using the class meta-data name you may expose a security hole in case untrusted source
* manages to specify a class that is accessible through class loader and exposes set of methods and/or fields,
* access of which opens an actual security hole. Such classes are known as deserialization gadgets.
*
* Because of this, use of "default typing" is not encouraged in general, and in particular is recommended against
* if the source of content is not trusted. Conversely, default typing may be used for processing content in
* cases where both ends (sender and receiver) are controlled by same entity.
*/
public JsonParser setClassMetadataName(final String name) {
return null;
}
/**
* Sets usage of default class meta-data name.
* Using it may introduce a security hole, see {@link #setClassMetadataName(String)} for more details.
* @see #setClassMetadataName(String)
*/
public JsonParser withClassMetadata(final boolean useMetadata) {
return null;
}
/**
* Adds a {@link jodd.util.Wildcard wildcard} pattern for white-listing classes.
* @see #setClassMetadataName(String)
*/
public JsonParser allowClass(final String classPattern) {
return null;
}
/**
* Removes the whitelist of allowed classes.
* @see #setClassMetadataName(String)
*/
public JsonParser allowAllClasses() {
return null;
}
/**
* Parses input JSON as given type.
*/
@SuppressWarnings("unchecked")
public <T> T parse(final String input, final Class<T> targetType) {
return null;
}
/**
* Parses input JSON to {@link JsonObject}, special case of {@link #parse(String, Class)}.
*/
public JsonObject parseAsJsonObject(final String input) {
return null;
}
/**
* Parses input JSON to {@link JsonArray}, special case of parsing.
*/
public JsonArray parseAsJsonArray(final String input) {
return null;
}
/**
* Parses input JSON to a list with specified component type.
*/
public <T> List<T> parseAsList(final String string, final Class<T> componentType) {
return null;
}
/**
* Parses input JSON to a list with specified key and value types.
*/
public <K, V> Map<K, V> parseAsMap(
final String string, final Class<K> keyType, final Class<V> valueType) {
return null;
}
/**
* Parses input JSON string.
*/
public <T> T parse(final String input) {
return null;
}
/**
* Parses input JSON as given type.
*/
@SuppressWarnings("unchecked")
public <T> T parse(final char[] input, final Class<T> targetType) {
return null;
}
/**
* Parses input JSON char array.
*/
public <T> T parse(final char[] input) {
return null;
}
}

View File

@@ -0,0 +1,68 @@
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
package jodd.json;
import java.util.Collection;
/**
* Just a base class of {@link jodd.json.JsonParser} that contains
* various utilities, to reduce the size of a parser.
*/
public abstract class JsonParserBase {
public JsonParserBase(final boolean strictTypes) {
}
/**
* Creates new instance of {@link jodd.json.MapToBean}.
*/
protected MapToBean createMapToBean(final String classMetadataName) {
return null;
}
/**
* Creates new type for JSON array objects.
* It returns a collection.
* Later, the collection will be converted into the target type.
*/
@SuppressWarnings("unchecked")
protected Collection<Object> newArrayInstance(final Class targetType) {
return null;
}
/**
* Creates new object or a <code>HashMap</code> if type is not specified.
*/
protected Object newObjectInstance(final Class targetType) {
return null;
}
/**
* Converts type of the given value.
*/
protected Object convertType(final Object value, final Class targetType) {
return null;
}
}

View File

@@ -0,0 +1,45 @@
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
package jodd.json;
import java.util.Map;
/**
* Map to bean converter.
* Used when parsing with class metadata enabled.
*/
public class MapToBean {
public MapToBean(final JsonParserBase jsonParser, final String classMetadataName) {
}
/**
* Converts map to target type.
*/
public Object map2bean(final Map map, Class targetType) {
return null;
}
}