Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add JavaDoc to 'Json' classes #12584

Merged
merged 2 commits into from
Aug 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 36 additions & 8 deletions java/src/org/openqa/selenium/json/Input.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,40 +24,61 @@

/**
* Similar to a {@link Reader} but with the ability to peek a single character ahead.
*
* <p>For the sake of providing a useful {@link #toString()} implementation, keeps the most recently
* <p>
* For the sake of providing a useful {@link #toString()} implementation, keeps the most recently
* read characters in the input buffer.
*/
class Input {
public static final char EOF = (char) -1;
// the number of chars to buffer
/** end-of-file indicator (0xFFFD) */
public static final char EOF = (char) -1; // NOTE: Produces Unicode replacement character (0xFFFD)
/** the number of chars to buffer */
private static final int BUFFER_SIZE = 4096;
// the number of chars to remember, safe to set to 0
/** the number of chars to remember, safe to set to 0 */
private static final int MEMORY_SIZE = 128;

private final Reader source;
// a buffer used to minimize read calls and to keep the chars to remember
/** a buffer used to minimize read calls and to keep the chars to remember */
private final char[] buffer;
// the filled area in the buffer
/** the filled area in the buffer */
private int filled;
// the last position read in the buffer
/** the last position read in the buffer */
private int position;

/**
* Initialize a new instance of the {@link Input} class with the specified source.
*
* @param source {@link Reader} object that supplies the input to be processed
*/
public Input(Reader source) {
this.source = Require.nonNull("Source", source);
this.buffer = new char[BUFFER_SIZE + MEMORY_SIZE];
this.filled = 0;
this.position = -1;
}

/**
* Extract the next character from the input without consuming it.
*
* @return the next input character; {@link #EOF} if input is exhausted
*/
public char peek() {
return fill() ? buffer[position + 1] : EOF;
}

/**
* Read and consume the next character from the input.
*
* @return the next input character; {@link #EOF} if input is exhausted
*/
public char read() {
return fill() ? buffer[++position] : EOF;
}

/**
* Return a string containing the most recently consumed input characters.
*
* @return {@link String} with up to 128 consumed input characters
*/
@Override
public String toString() {
int offset;
Expand All @@ -74,6 +95,13 @@ public String toString() {
return "Last " + length + " characters read: " + new String(buffer, offset, length);
}

/**
* If all buffered input has been consumed, read the next chunk into the buffer.<br>
* <b>NOTE</b>: The last 128 character of consumed input is retained for debug output.
*
* @return {@code true} if new input is available; {@code false} if input is exhausted
* @throws UncheckedIOException if an I/O exception is encountered
*/
private boolean fill() {
// do we need to fill the buffer?
while (filled == position + 1) {
Expand Down
140 changes: 138 additions & 2 deletions java/src/org/openqa/selenium/json/Json.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,34 +27,133 @@
import java.util.List;
import java.util.Map;

/**
* The <b>Json</b> class is the entrypoint for the JSON processing features of the Selenium API.
* These features include:
* <ul>
* <li>Built-in JSON deserialization to primitives and collections from the standard types shown below.</li>
* <li>Facilities to deserialize JSON to custom data types:
* <ul>
* <li>Classes that declare a {@code fromJson(T)} static method, where <b>T</b> is any of the standard
* types shown below.</li>
* <li>Classes that declare a {@code fromJson(JsonInput)} static method.<br>
* <b>NOTE</b>: Objects deserialized via a {@code fromJson} static method can be immutable.</li>
* <li>Classes that declare setter methods adhering to the
* <a href="https://docs.oracle.com/javase/tutorial/javabeans/writing/index.html">JavaBean</a>
* specification.<br>
* <b>NOTE</b>: Deserialized {@code JavaBean} objects are mutable, which may be undesirable.</li>
* </ul>
* </li>
* <li>Built-in JSON serialization from primitives and collections from the standard types shown below.</li>
* <li>Facilities to serialize custom data types to JSON:
* <ul>
* <li>Classes that declare a {@code toJson()} method returning a primitive or collection from
* the standard types shown below.</li>
* <li>Classes that declare getter methods adhering to the {@code JavaBean} specification.</li>
* </ul>
* </li>
* </ul>
*
* The standard types supported by built-in processing:
* <ul>
* <li><b>Numeric Types</b>:<br>
* {@link java.lang.Byte Byte}, {@link java.lang.Double Double}, {@link java.lang.Float Float},
* {@link java.lang.Integer Integer}, {@link java.lang.Long Long}, {@link java.lang.Short Short}
* </li>
* <li><b>Collection Types</b>:<br>
* {@link java.util.List List}, {@link java.util.Set Set}
* </li>
* <li><b>Standard Java Types</b>:<br>
* {@link java.util.Map Map}, {@link java.lang.Boolean Boolean}, {@link java.lang.String String},
* {@link java.lang.Enum Enum}, {@link java.net.URI URI}, {@link java.net.URL URL},
* {@link java.util.UUID UUID}, {@link java.time.Instant Instant}, {@link java.lang.Object Object}
* </li>
* </ul>
*
* You can serialize objects for which no explicit coercer has been specified, and the <b>Json</b> API will use a
* generic process to provide best-effort JSON output. For the most predictable results, though, it's best to
* provide a {@code toJson()} method for the <b>Json</b> API to use for serialization. This is especially beneficial
* for objects that contain transient properties that should be omitted from the JSON output.
* <p>
* You can deserialize objects for which no explicit handling has been defined. Note that the data type of the
* result will be {@code Map<String,?>}, which means that you'll need to perform type checking and casting every
* time you extract an entry value from the result. For this reason, it's best to declare a type-specific
* {@code fromJson()} method in every type you need to deserialize.
*
* @see JsonTypeCoercer
* @see JsonInput
* @see JsonOutput
*/
public class Json {
/** The value of {@code Content-Type} headers for HTTP requests and
* responses with JSON entities */
public static final String JSON_UTF_8 = "application/json; charset=utf-8";

/** Specifier for {@code List<Map<String, Object>} input/output type */
public static final Type LIST_OF_MAPS_TYPE =
new TypeToken<List<Map<String, Object>>>() {}.getType();
new TypeToken<List<Map<String, Object>>>() {}.getType();
/** Specifier for {@code Map<String, Object>} input/output type */
public static final Type MAP_TYPE = new TypeToken<Map<String, Object>>() {}.getType();
/** Specifier for {@code Object} input/output type */
public static final Type OBJECT_TYPE = new TypeToken<Object>() {}.getType();

private final JsonTypeCoercer fromJson = new JsonTypeCoercer();

/**
* Serialize the specified object to JSON string representation.<br>
* <b>NOTE</b>: This method limits traversal of nested objects to the default
* {@link JsonOutput#MAX_DEPTH maximum depth}.
*
* @param toConvert the object to be serialized
* @return JSON string representing the specified object
*/
public String toJson(Object toConvert) {
return toJson(toConvert, JsonOutput.MAX_DEPTH);
}

/**
* Serialize the specified object to JSON string representation.
*
* @param toConvert the object to be serialized
* @param maxDepth maximum depth of nested object traversal
* @return JSON string representing the specified object
* @throws JsonException if an I/O exception is encountered
*/
public String toJson(Object toConvert, int maxDepth) {
try (Writer writer = new StringWriter();
JsonOutput jsonOutput = newOutput(writer)) {
JsonOutput jsonOutput = newOutput(writer)) {
jsonOutput.write(toConvert, maxDepth);
return writer.toString();
} catch (IOException e) {
throw new JsonException(e);
}
}

/**
* Deserialize the specified JSON string into an object of the specified type.<br>
* <b>NOTE</b>: This method uses the {@link PropertySetting#BY_NAME BY_NAME} strategy to assign values to properties
* in the deserialized object.
*
* @param source serialized source as JSON string
* @param typeOfT data type for deserialization (class or {@link TypeToken})
* @return object of the specified type deserialized from [source]
* @param <T> result type (as specified by [typeOfT])
* @throws JsonException if an I/O exception is encountered
*/
public <T> T toType(String source, Type typeOfT) {
return toType(source, typeOfT, PropertySetting.BY_NAME);
}

/**
* Deserialize the specified JSON string into an object of the specified type.
*
* @param source serialized source as JSON string
* @param typeOfT data type for deserialization (class or {@link TypeToken})
* @param setter strategy used to assign values during deserialization
* @return object of the specified type deserialized from [source]
* @param <T> result type (as specified by [typeOfT])
* @throws JsonException if an I/O exception is encountered
*/
public <T> T toType(String source, Type typeOfT, PropertySetting setter) {
try (StringReader reader = new StringReader(source)) {
return toType(reader, typeOfT, setter);
Expand All @@ -63,10 +162,31 @@ public <T> T toType(String source, Type typeOfT, PropertySetting setter) {
}
}

/**
* Deserialize the JSON string supplied by the specified {@code Reader} into an object of the specified type.<br>
* <b>NOTE</b>: This method uses the {@link PropertySetting#BY_NAME BY_NAME} strategy to assign values to properties
* in the deserialized object.
*
* @param source {@link Reader} that supplies a serialized JSON string
* @param typeOfT data type for deserialization (class or {@link TypeToken})
* @return object of the specified type deserialized from [source]
* @param <T> result type (as specified by [typeOfT])
* @throws JsonException if an I/O exception is encountered
*/
public <T> T toType(Reader source, Type typeOfT) {
return toType(source, typeOfT, PropertySetting.BY_NAME);
}

/**
* Deserialize the JSON string supplied by the specified {@code Reader} into an object of the specified type.
*
* @param source {@link Reader} that supplies a serialized JSON string
* @param typeOfT data type for deserialization (class or {@link TypeToken})
* @param setter strategy used to assign values during deserialization
* @return object of the specified type deserialized from [source]
* @param <T> result type (as specified by [typeOfT])
* @throws JsonException if an I/O exception is encountered
*/
public <T> T toType(Reader source, Type typeOfT, PropertySetting setter) {
if (setter == null) {
throw new JsonException("Mechanism for setting properties must be set");
Expand All @@ -77,10 +197,26 @@ public <T> T toType(Reader source, Type typeOfT, PropertySetting setter) {
}
}

/**
* Create a new {@code JsonInput} object to traverse the JSON string supplied the specified {@code Reader}.<br>
* <b>NOTE</b>: The {@code JsonInput} object returned by this method uses the {@link PropertySetting#BY_NAME BY_NAME}
* strategy to assign values to properties objects it deserializes.
*
* @param from {@link Reader} that supplies a serialized JSON string
* @return {@link JsonInput} object to traverse the JSON string supplied by [from]
* @throws UncheckedIOException if an I/O exception occurs
*/
public JsonInput newInput(Reader from) throws UncheckedIOException {
return new JsonInput(from, fromJson, PropertySetting.BY_NAME);
}

/**
* Create a new {@code JsonOutput} object to produce a serialized JSON string in the specified {@code Appendable}.
*
* @param to {@link Appendable} that consumes a serialized JSON string
* @return {@link JsonOutput} object to product a JSON string in [to]
* @throws UncheckedIOException if an I/O exception occurs
*/
public JsonOutput newOutput(Appendable to) throws UncheckedIOException {
return new JsonOutput(to);
}
Expand Down
Loading
Loading