Working with JSON is fundamental to modern web development. Whether you're parsing API responses, serializing data for storage, or communicating with JavaScript UI libraries, you need robust JSON handling. Oorian provides a complete, lightweight JSON library that integrates seamlessly with the framework.
The JSON Type Hierarchy
Oorian's JSON library consists of a type hierarchy rooted in JsonValue:
JsonValue (abstract base)
├── JsonObject - Key-value pairs: {"name": "Alice", "age": 30}
├── JsonArray - Ordered list: [1, 2, 3]
├── JsonString - Text: "hello"
├── JsonNumber - Numeric: 42, 3.14
├── JsonBoolean - true/false
└── JsonNull - null
This design mirrors JSON's actual structure, making the API intuitive and predictable.
Parsing JSON
Parse any JSON string using JsonValue.parse() or the type-specific static methods:
// Parse unknown JSON - returns appropriate subtype
JsonValue value = JsonValue.parse(jsonString);
if (value.isObject())
{
JsonObject obj = value.asObject();
}
else if (value.isArray())
{
JsonArray arr = value.asArray();
}
// When you know the type, use direct parsing
JsonObject user = JsonObject.parse("{\"name\": \"Alice\", \"age\": 30}");
JsonArray numbers = JsonArray.parse("[1, 2, 3, 4, 5]");
The parser handles all standard JSON features including escape sequences (\n, \t, \", \\), Unicode escapes (\u0041), and scientific notation (1.5e10).
Working with JsonObject
JsonObject represents a JSON object—a collection of key-value pairs. Create objects programmatically or parse them from strings:
// Build a JsonObject programmatically
JsonObject user = new JsonObject();
user.put("name", "Alice");
user.put("email", "alice@example.com");
user.put("age", 30);
user.put("active", true);
// Fluent style - put() returns the object
JsonObject config = new JsonObject()
.put("theme", "dark")
.put("fontSize", 14)
.put("notifications", true);
// Single-property constructor
JsonObject simple = new JsonObject("status", "ok");
Type-Safe Accessors
Read values with type-safe accessor methods that handle null values gracefully:
JsonObject user = JsonObject.parse(jsonString);
// Basic accessors - return null if key missing or value is null
String name = user.getAsString("name");
Integer age = user.getAsInt("age");
Boolean active = user.getAsBoolean("active");
Double balance = user.getAsDouble("balance");
Long timestamp = user.getAsLong("timestamp");
// With default values - return default if key missing or null
String theme = user.getAsString("theme", "light");
int maxItems = user.getAsInt("maxItems", 100);
boolean enabled = user.getAsBoolean("enabled", true);
// Nested objects and arrays
JsonObject address = user.getAsJsonObject("address");
JsonArray tags = user.getAsJsonArray("tags");
The getAs* methods safely return null when the key doesn't exist or the value is JSON null. The overloaded versions with default parameters provide fallback values.
Checking and Manipulating
// Check if key exists
if (json.containsKey("email"))
{
// ...
}
// Get all keys
List<String> keys = json.getKeys();
// Check if empty
if (json.isEmpty())
{
// ...
}
// Remove a key
json.remove("temporaryField");
// Get raw JsonValue (for type checking)
JsonValue rawValue = json.get("someField");
Working with JsonArray
JsonArray represents an ordered list of JSON values. It implements Iterable<JsonValue>, so you can use enhanced for-loops:
// Build an array
JsonArray colors = new JsonArray();
colors.add("red");
colors.add("green");
colors.add("blue");
// Add multiple values
JsonArray numbers = new JsonArray();
numbers.addAll(Arrays.asList(1, 2, 3, 4, 5));
// Iterate over values
for (JsonValue item : colors)
{
System.out.println(item.asString().getValue());
}
Convenient Parsing Methods
JsonArray provides static methods that parse JSON directly into typed Java lists:
// Parse directly to typed lists
List<String> names = JsonArray.parseStrings("[\"Alice\", \"Bob\", \"Carol\"]");
List<Integer> ids = JsonArray.parseInts("[1, 2, 3, 4, 5]");
List<Double> prices = JsonArray.parseDoubles("[19.99, 29.99, 39.99]");
List<Boolean> flags = JsonArray.parseBooleans("[true, false, true]");
List<Long> timestamps = JsonArray.parseLongs("[1706745600000, 1706832000000]");
Indexed Access
JsonArray arr = JsonArray.parse("[\"first\", 42, true, {\"nested\": \"object\"}]");
// Type-safe indexed access
String first = arr.get(0).asString().getValue();
int number = arr.getAsInt(1);
boolean flag = arr.getAsBoolean(2);
JsonObject nested = arr.getAsJsonObject(3);
// Get entire array as typed list
List<String> strings = arr.getStringArray();
List<Integer> ints = arr.getIntArray();
List<JsonObject> objects = arr.getObjectArray();
Serialization to JSON String
All JSON types serialize back to valid JSON strings:
JsonObject user = new JsonObject()
.put("name", "Alice")
.put("age", 30)
.put("tags", new JsonArray().add("developer").add("java"));
String json = user.toJsonString();
// {"name":"Alice","age":30,"tags":["developer","java"]}
// toString() also works
System.out.println(user); // Same output
The Jsonable Interface: Turning POJOs into JSON
The real power of Oorian's JSON library comes from the Jsonable interface. It lets you turn any Plain Old Java Object (POJO) into a first-class JSON citizen with just two methods:
public interface Jsonable
{
void initFromJson(JsonValue json);
JsonValue toJsonValue();
// Default methods provide convenience
default void initFromJson(String json) { ... }
default String toJsonString() { ... }
}
Implementing Jsonable gives your class the ability to:
- Serialize to JSON with
toJsonValue()ortoJsonString() - Deserialize from JSON with
initFromJson() - Be directly added to
JsonObjectorJsonArray(automatic conversion) - Work seamlessly with Oorian's UI component libraries
Basic Jsonable Implementation
Here's a complete example of a POJO implementing Jsonable:
public class User implements Jsonable
{
private String name;
private String email;
private int age;
private boolean active;
// Default constructor required for deserialization
public User()
{
}
// Convenience constructor for creating from JSON
public User(JsonValue jv)
{
initFromJson(jv);
}
@Override
public void initFromJson(JsonValue jv)
{
JsonObject json = (JsonObject) jv;
this.name = json.getAsString("name");
this.email = json.getAsString("email");
this.age = json.getAsInt("age", 0);
this.active = json.getAsBoolean("active", false);
}
@Override
public JsonValue toJsonValue()
{
JsonObject json = new JsonObject();
json.put("name", name);
json.put("email", email);
json.put("age", age);
json.put("active", active);
return json;
}
// Standard getters and setters...
public String getName() { return name; }
public void setName(String name) { this.name = name; }
// etc.
}
Using Jsonable Objects
Once a class implements Jsonable, it integrates naturally with the JSON library:
// Create and serialize
User user = new User();
user.setName("Alice");
user.setEmail("alice@example.com");
user.setAge(30);
user.setActive(true);
String json = user.toJsonString();
// {"name":"Alice","email":"alice@example.com","age":30,"active":true}
// Deserialize
User loaded = new User();
loaded.initFromJson(json);
// Or use the JsonValue constructor
User fromJson = new User(JsonValue.parse(json));
// Add directly to JsonObject - automatically calls toJsonValue()
JsonObject response = new JsonObject();
response.put("user", user);
response.put("timestamp", System.currentTimeMillis());
// Add directly to JsonArray
JsonArray users = new JsonArray();
users.add(user1);
users.add(user2);
users.add(user3);
Nested Jsonable Objects
Jsonable objects can contain other Jsonable objects for complex data structures:
public class Address implements Jsonable
{
private String street;
private String city;
private String state;
private String zipCode;
public Address() { }
public Address(JsonValue jv)
{
initFromJson(jv);
}
@Override
public void initFromJson(JsonValue jv)
{
JsonObject json = (JsonObject) jv;
this.street = json.getAsString("street");
this.city = json.getAsString("city");
this.state = json.getAsString("state");
this.zipCode = json.getAsString("zipCode");
}
@Override
public JsonValue toJsonValue()
{
JsonObject json = new JsonObject();
json.put("street", street);
json.put("city", city);
json.put("state", state);
json.put("zipCode", zipCode);
return json;
}
// Getters and setters...
}
public class Company implements Jsonable
{
private String name;
private Address headquarters;
private List<Address> offices;
public Company()
{
this.offices = new ArrayList<>();
}
public Company(JsonValue jv)
{
this();
initFromJson(jv);
}
@Override
public void initFromJson(JsonValue jv)
{
JsonObject json = (JsonObject) jv;
this.name = json.getAsString("name");
// Nested object
JsonObject hqJson = json.getAsJsonObject("headquarters");
if (hqJson != null)
{
this.headquarters = new Address(hqJson);
}
// Array of objects
JsonArray officesJson = json.getAsJsonArray("offices");
if (officesJson != null)
{
for (JsonValue officeJson : officesJson)
{
offices.add(new Address(officeJson));
}
}
}
@Override
public JsonValue toJsonValue()
{
JsonObject json = new JsonObject();
json.put("name", name);
json.put("headquarters", headquarters); // Jsonable auto-converts
if (!offices.isEmpty())
{
JsonArray officesArray = new JsonArray();
for (Address office : offices)
{
officesArray.add(office); // Jsonable auto-converts
}
json.put("offices", officesArray);
}
return json;
}
// Getters and setters...
}
Handling Enums
For enums with database IDs, serialize the ID and use a lookup method when deserializing:
public enum Status
{
PENDING(1),
ACTIVE(2),
COMPLETED(3);
private final int id;
Status(int id) { this.id = id; }
public int getId() { return id; }
public static Status get(int id)
{
for (Status s : values())
{
if (s.id == id) return s;
}
return PENDING; // Default
}
}
public class Task implements Jsonable
{
private String title;
private Status status;
@Override
public void initFromJson(JsonValue jv)
{
JsonObject json = (JsonObject) jv;
this.title = json.getAsString("title");
this.status = Status.get(json.getAsInt("status", 1));
}
@Override
public JsonValue toJsonValue()
{
JsonObject json = new JsonObject();
json.put("title", title);
json.put("status", status.getId());
return json;
}
}
Integration with Oorian Components
Many Oorian extension libraries use Jsonable for configuration and data. For example, menu items, chart data, and grid configurations all implement Jsonable:
// SyncFusion menu items implement Jsonable
SfMenu menu = new SfMenu();
SfMenuItem fileMenu = menu.addTextItem("File", "file");
fileMenu.addTextItem("New", "new");
fileMenu.addTextItem("Open", "open");
// Behind the scenes, the menu serializes its items to JSON
// for the JavaScript component:
// [{"id":"file","text":"File","items":[{"id":"new","text":"New"},{"id":"open","text":"Open"}]}]
When you create data models for charts, grids, or other components, implementing Jsonable ensures seamless integration with the framework.
Best Practices
1. Include a JsonValue Constructor
Adding a constructor that takes JsonValue makes creating objects from JSON cleaner:
// Without JsonValue constructor
User user = new User();
user.initFromJson(jsonValue);
// With JsonValue constructor
User user = new User(jsonValue);
2. Handle Missing Fields Gracefully
Use the accessor variants with default values or check for null:
// Good - provides defaults
this.count = json.getAsInt("count", 0);
this.enabled = json.getAsBoolean("enabled", true);
// Good - explicit null handling
String optional = json.getAsString("optional");
if (optional != null)
{
this.optional = optional;
}
3. Only Serialize Non-Default Values
Keep JSON output compact by only including fields that have meaningful values:
@Override
public JsonValue toJsonValue()
{
JsonObject json = new JsonObject();
// Always include required fields
json.put("name", name);
// Only include optional fields if set
if (description != null)
{
json.put("description", description);
}
if (priority != DEFAULT_PRIORITY)
{
json.put("priority", priority);
}
return json;
}
4. Initialize Collections in Constructor
When your class has collection fields, initialize them in the default constructor so initFromJson can populate them:
public class Order implements Jsonable
{
private final List<OrderItem> items;
public Order()
{
this.items = new ArrayList<>(); // Initialize here
}
public Order(JsonValue jv)
{
this(); // Call default constructor first
initFromJson(jv);
}
}
Summary
Oorian's JSON library provides everything you need for JSON processing:
- Complete type hierarchy matching JSON's structure
- Type-safe accessors with null handling and defaults
- Fluent builders for constructing JSON programmatically
- The Jsonable interface for seamless POJO-to-JSON conversion
- Automatic integration with Oorian's UI component libraries
No external dependencies, no annotations, no reflection magic—just clean, straightforward Java code that works with your IDE's autocomplete and catches errors at compile time.