Skip to content

Commit

Permalink
Add JavaDoc to 'Json' classes
Browse files Browse the repository at this point in the history
  • Loading branch information
sbabcoc committed Aug 15, 2023
1 parent eea09a6 commit f3eed8d
Show file tree
Hide file tree
Showing 2 changed files with 162 additions and 0 deletions.
151 changes: 151 additions & 0 deletions java/src/org/openqa/selenium/json/Json.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,117 @@
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.
* <p>
* These features include:
* <ul>
* <li>Built-in serialization of primitives and collections.</li>
* <li>Facilities to serialize custom data types:
* <ul>
* <li>Classes that declare getter methods that adhere to the
* <a href="https://docs.oracle.com/javase/tutorial/javabeans/writing/index.html">JavaBean</a>
* specification.</li>
* <li>Classes that declare a {@code toJson()} method that returns primitives and collections.</li>
* </ul>
* </li>
* <li>Build-in deserialization of primitives and collections.</li>
* <li>Facilities to deserialize custom data types:
* <ul>
* <li>Classes that declare setter methods that adhere to the {@code JavaBean} specification.</li>
* <li>Classes that declare a {@code fromJson(JsonInput)} method.</li>
* </ul>
* </li>
* </ul>
*
* The standard types supported by built-in processing:
* <ul>
* <li><b>Numeric Types</b>:
* <ul>
* <li>{@link java.lang.Byte Byte}</li>
* <li>{@link java.lang.Double Double}</li>
* <li>{@link java.lang.Float Float}</li>
* <li>{@link java.lang.Integer Integer}</li>
* <li>{@link java.lang.Long Long}</li>
* <li>{@link java.lang.Short Short}</li>
* </ul>
* </li>
* <li><b>Collection Types</b>:
* <ul>
* <li>{@link java.util.List List}</li>
* <li>{@link java.util.Set Set}</li>
* </ul>
* </li>
* <li><b>Standard Java Types</b>:
* <ul>
* <li>{@link java.util.Map Map}</li>
* <li>{@link java.lang.Boolean Boolean}</li>
* <li>{@link java.lang.String String}</li>
* <li>{@link java.lang.Enum Enum}</li>
* <li>{@link java.net.URI URI}</li>
* <li>{@link java.net.URL URL}</li>
* <li>{@link java.util.UUID UUID}</li>
* <li>{@link java.time.Instant Instant}</li>
* <li>{@link java.lang.Object Object}</li>
* </ul>
* </li>
* </ul>
*
* The <b>Json</b> API also handles Selenium {@link org.openqa.selenium.Capabilities Capabilities} objects:
* <pre>
* String json = "{\"browserName\":\"htmlunit\",\"version\":\"chrome\"}";
* Capabilities capabilities = new Json().toType(json, Capabilities.class);
* </pre>
*<p>
* 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 coercer has been defined via the <b>ObjectCoercer</b>. 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 specific {@code fromJson()} method in every type you need to deserialize.
* <p>
*
* @see JsonTypeCoercer
* @see JsonInput
* @see JsonOutput
*/
public class Json {
/** This constant declares the value of the {@code Content-Type}
* headers of HTTP requests and responses with JSON entities */
public static final String JSON_UTF_8 = "application/json; charset=utf-8";

/** This constant specifies deserializing as {@code List<Map<String, Object>} */
public static final Type LIST_OF_MAPS_TYPE =
new TypeToken<List<Map<String, Object>>>() {}.getType();
/** This constant specifies deserializing as {@code Map<String, Object>} */
public static final Type MAP_TYPE = new TypeToken<Map<String, Object>>() {}.getType();
/** This constant specified deserializing as {@code Object} */
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
*/
public String toJson(Object toConvert, int maxDepth) {
try (Writer writer = new StringWriter();
JsonOutput jsonOutput = newOutput(writer)) {
Expand All @@ -51,10 +148,29 @@ public String toJson(Object toConvert, int maxDepth) {
}
}

/**
* 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])
*/
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])
*/
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 +179,29 @@ 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])
*/
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])
*/
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 +212,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
11 changes: 11 additions & 0 deletions java/src/org/openqa/selenium/json/PropertySetting.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,18 @@

package org.openqa.selenium.json;

import java.io.Reader;
import java.lang.reflect.Type;

/**
* This enumeration is used to specify the strategy used to assign values during deserialization.
*
* @see org.openqa.selenium.json.Json#toType(Reader, Type, PropertySetting)
* @see org.openqa.selenium.json.Json#toType(String, Type, PropertySetting)
*/
public enum PropertySetting {
/** Values are stored via the corresponding Bean setter methods. */
BY_NAME,
/** Values are stored in fields with the indicated names. */
BY_FIELD
}

0 comments on commit f3eed8d

Please sign in to comment.