JSON processing library for Selenium WebDriver providing serialization and deserialization capabilities
—
Advanced JSON reading and deserialization using JsonInput for memory-efficient processing of large JSON documents. Provides fine-grained control over the parsing process, custom type coercers, and streaming access to JSON elements.
Streaming JSON input processor that implements Closeable for resource management.
/**
* The JsonInput class defines the operations used to deserialize JSON strings into Java objects.
* Provides streaming access to JSON elements and supports custom type coercion.
*/
public class JsonInput implements Closeable {
// Configuration methods
/**
* Change how property setting is done. It's polite to set the value back once done processing.
*
* @param setter The new PropertySetting to use
* @return The previous PropertySetting that has just been replaced
*/
public PropertySetting propertySetting(PropertySetting setter);
/**
* Add the specified type coercers to the set installed in the JSON coercion manager.
*
* @param coercers array of zero or more TypeCoercer objects
* @return this JsonInput object with added type coercers
* @throws JsonException if this JsonInput has already begun processing its input
*/
public JsonInput addCoercers(TypeCoercer<?>... coercers);
/**
* Add the specified type coercers to the set installed in the JSON coercion manager.
*
* @param coercers iterable collection of TypeCoercer objects
* @return this JsonInput object with added type coercers
* @throws JsonException if this JsonInput has already begun processing its input
*/
public JsonInput addCoercers(Iterable<TypeCoercer<?>> coercers);
// Element inspection
/**
* Peek at the next input string character to determine the pending JSON element type.
*
* @return JsonType indicating the pending JSON element type
* @throws JsonException if unable to determine the type of the pending element
* @throws UncheckedIOException if an I/O exception is encountered
*/
public JsonType peek();
// Primitive value reading
/**
* Read the next element of the JSON input stream as a boolean value.
*
* @return true or false
* @throws JsonException if the next element isn't the expected boolean
* @throws UncheckedIOException if an I/O exception is encountered
*/
public boolean nextBoolean();
/**
* Read the next element of the JSON input stream as an object property name.
*
* @return JSON object property name
* @throws JsonException if the next element isn't a string followed by a colon
* @throws UncheckedIOException if an I/O exception is encountered
*/
public String nextName();
/**
* Read the next element of the JSON input stream as a null object.
*
* @return null object
* @throws JsonException if the next element isn't a null
* @throws UncheckedIOException if an I/O exception is encountered
*/
public Object nextNull();
/**
* Read the next element of the JSON input stream as a number.
*
* @return Number object
* @throws JsonException if the next element isn't a number
* @throws UncheckedIOException if an I/O exception is encountered
*/
public Number nextNumber();
/**
* Read the next element of the JSON input stream as a string.
*
* @return String object
* @throws JsonException if the next element isn't a string
* @throws UncheckedIOException if an I/O exception is encountered
*/
public String nextString();
/**
* Read the next element of the JSON input stream as an instant.
*
* @return Instant object
* @throws JsonException if the next element isn't a Long
* @throws UncheckedIOException if an I/O exception is encountered
*/
public Instant nextInstant();
// Container navigation
/**
* Determine whether an element is pending for the current container from the JSON input stream.
*
* @return true if an element is pending; otherwise false
* @throws JsonException if no container is open
* @throws UncheckedIOException if an I/O exception is encountered
*/
public boolean hasNext();
/**
* Process the opening square bracket of a JSON array.
*
* @throws UncheckedIOException if an I/O exception is encountered
*/
public void beginArray();
/**
* Process the closing square bracket of a JSON array.
*
* @throws UncheckedIOException if an I/O exception is encountered
*/
public void endArray();
/**
* Process the opening curly brace of a JSON object.
*
* @throws UncheckedIOException if an I/O exception is encountered
*/
public void beginObject();
/**
* Process the closing curly brace of a JSON object.
*
* @throws UncheckedIOException if an I/O exception is encountered
*/
public void endObject();
/**
* Discard the pending JSON property value.
*
* @throws JsonException if the pending element isn't a value type
* @throws UncheckedIOException if an I/O exception is encountered
*/
public void skipValue();
// High-level reading methods
/**
* Read the next element from the JSON input stream as the specified type.
*
* @param type data type for deserialization (class or TypeToken)
* @return object of the specified type deserialized from the JSON input stream
* Returns null if the input string is exhausted
* @param <T> result type (as specified by type)
* @throws JsonException if coercion of the next element to the specified type fails
* @throws UncheckedIOException if an I/O exception is encountered
*/
public <T> T read(Type type);
/**
* Read an array of elements from the JSON input stream with elements as the specified type.
*
* @param type data type for deserialization (class or TypeToken)
* @return list of objects of the specified type deserialized from the JSON input stream
* Returns null if the input string is exhausted
* @param <T> result type of the item in the list (as specified by type)
* @throws JsonException if coercion of the next element to the specified type fails
* @throws UncheckedIOException if an I/O exception is encountered
*/
public <T> List<T> readArray(Type type);
// Resource management
/**
* Close the input stream.
*
* @throws UncheckedIOException if an I/O exception is encountered
*/
public void close();
}Enumeration of JSON element types for parsing control.
/**
* Used to specify the pending JSON element type.
*/
public enum JsonType {
/** Boolean value */
BOOLEAN,
/** property name */
NAME,
/** null value */
NULL,
/** numeric value */
NUMBER,
/** start of object */
START_MAP,
/** end of object */
END_MAP,
/** start of array */
START_COLLECTION,
/** end of array */
END_COLLECTION,
/** string value */
STRING,
/** end of input */
END
}import org.openqa.selenium.json.Json;
import org.openqa.selenium.json.JsonInput;
import org.openqa.selenium.json.JsonType;
import java.io.StringReader;
Json json = new Json();
String jsonData = "{\"name\":\"John\",\"age\":30,\"active\":true}";
try (JsonInput input = json.newInput(new StringReader(jsonData))) {
input.beginObject();
while (input.hasNext()) {
String propertyName = input.nextName();
switch (propertyName) {
case "name":
String name = input.nextString();
System.out.println("Name: " + name);
break;
case "age":
Number age = input.nextNumber();
System.out.println("Age: " + age);
break;
case "active":
boolean active = input.nextBoolean();
System.out.println("Active: " + active);
break;
default:
input.skipValue(); // Skip unknown properties
}
}
input.endObject();
}String jsonArray = "[\"apple\",\"banana\",\"cherry\"]";
try (JsonInput input = json.newInput(new StringReader(jsonArray))) {
List<String> fruits = new ArrayList<>();
input.beginArray();
while (input.hasNext()) {
fruits.add(input.nextString());
}
input.endArray();
System.out.println("Fruits: " + fruits);
}
// Or use the convenient readArray method
try (JsonInput input = json.newInput(new StringReader(jsonArray))) {
List<String> fruits = input.readArray(String.class);
System.out.println("Fruits: " + fruits);
}String jsonData = "{\"count\":42,\"message\":\"hello\",\"valid\":true}";
try (JsonInput input = json.newInput(new StringReader(jsonData))) {
input.beginObject();
while (input.hasNext()) {
String propertyName = input.nextName();
JsonType valueType = input.peek();
switch (valueType) {
case NUMBER:
Number num = input.nextNumber();
System.out.println(propertyName + " (number): " + num);
break;
case STRING:
String str = input.nextString();
System.out.println(propertyName + " (string): " + str);
break;
case BOOLEAN:
boolean bool = input.nextBoolean();
System.out.println(propertyName + " (boolean): " + bool);
break;
case NULL:
input.nextNull();
System.out.println(propertyName + " (null)");
break;
default:
input.skipValue();
System.out.println(propertyName + " (skipped)");
}
}
input.endObject();
}import org.openqa.selenium.json.TypeCoercer;
import org.openqa.selenium.json.PropertySetting;
import java.lang.reflect.Type;
import java.util.function.BiFunction;
// Custom coercer for LocalDate
public class LocalDateCoercer extends TypeCoercer<LocalDate> {
@Override
public boolean test(Class<?> aClass) {
return LocalDate.class.isAssignableFrom(aClass);
}
@Override
public BiFunction<JsonInput, PropertySetting, LocalDate> apply(Type type) {
return (jsonInput, propertySetting) -> {
String dateStr = jsonInput.nextString();
return LocalDate.parse(dateStr);
};
}
}
// Usage
String jsonData = "{\"date\":\"2023-12-25\"}";
try (JsonInput input = json.newInput(new StringReader(jsonData))) {
input.addCoercers(new LocalDateCoercer());
input.beginObject();
input.nextName(); // "date"
LocalDate date = input.read(LocalDate.class);
input.endObject();
System.out.println("Date: " + date);
}// Switch between property setting strategies
try (JsonInput input = json.newInput(new StringReader(jsonData))) {
PropertySetting original = input.propertySetting(PropertySetting.BY_FIELD);
// Read objects using direct field access
MyObject obj = input.read(MyObject.class);
// Restore original setting
input.propertySetting(original);
}String nestedJson = """
{
"user": {
"name": "John",
"preferences": {
"theme": "dark",
"notifications": true
}
},
"lastLogin": "2023-12-25T10:30:00Z"
}
""";
try (JsonInput input = json.newInput(new StringReader(nestedJson))) {
input.beginObject();
while (input.hasNext()) {
String key = input.nextName();
if ("user".equals(key)) {
input.beginObject();
while (input.hasNext()) {
String userKey = input.nextName();
if ("name".equals(userKey)) {
String name = input.nextString();
System.out.println("User name: " + name);
} else if ("preferences".equals(userKey)) {
input.beginObject();
while (input.hasNext()) {
String prefKey = input.nextName();
if ("theme".equals(prefKey)) {
String theme = input.nextString();
System.out.println("Theme: " + theme);
} else if ("notifications".equals(prefKey)) {
boolean notifications = input.nextBoolean();
System.out.println("Notifications: " + notifications);
} else {
input.skipValue();
}
}
input.endObject();
} else {
input.skipValue();
}
}
input.endObject();
} else if ("lastLogin".equals(key)) {
Instant lastLogin = input.nextInstant();
System.out.println("Last login: " + lastLogin);
} else {
input.skipValue();
}
}
input.endObject();
}Install with Tessl CLI
npx tessl i tessl/maven-org-seleniumhq-selenium--selenium-json