Hjson (Human JSON) configuration file format library for Java providing parsing and generation capabilities with human-friendly features.
—
Configure parsing behavior and output formatting with HjsonOptions and Domain Specific Format providers for specialized value handling and custom parsing rules.
Configure parsing and formatting behavior for Hjson operations.
/**
* Configuration options for Hjson parsing and formatting
*/
class HjsonOptions {
/**
* Creates default Hjson options with standard settings
*/
HjsonOptions();
/**
* Gets the array of Domain Specific Format providers
* @return array of DSF providers, or null if none are configured
*/
IHjsonDsfProvider[] getDsfProviders();
/**
* Sets the Domain Specific Format providers for specialized value parsing and formatting
* @param providers array of DSF providers to use, or null to disable DSF processing
*/
void setDsfProviders(IHjsonDsfProvider[] providers);
/**
* Gets whether legacy root parsing is enabled (objects without braces)
* @return true if legacy root parsing is enabled
*/
boolean getParseLegacyRoot();
/**
* Sets whether to parse legacy root format (object members without surrounding braces)
* @param value true to enable legacy root parsing
*/
void setParseLegacyRoot(boolean value);
/**
* Gets whether root braces are emitted in output (deprecated, always returns true)
* @return always true
* @deprecated Root braces are always emitted in current versions
*/
@Deprecated
boolean getEmitRootBraces();
/**
* Sets whether to emit root braces in output (deprecated, no-op)
* @param value ignored, root braces are always emitted
* @deprecated Root braces are always emitted in current versions
*/
@Deprecated
void setEmitRootBraces(boolean value);
}Usage Examples:
import org.hjson.HjsonOptions;
import org.hjson.JsonValue;
import org.hjson.HjsonDsf;
// Create options with default settings
HjsonOptions options = new HjsonOptions();
// Configure DSF providers for specialized parsing
options.setDsfProviders(new IHjsonDsfProvider[] {
HjsonDsf.math(),
HjsonDsf.hex(true)
});
// Enable legacy root parsing (objects without braces)
options.setParseLegacyRoot(true);
// Use options for parsing
JsonValue result = JsonValue.readHjson("""
// This is valid with legacy root parsing
name: My Application
version: "1.0.0"
maxValue: +Inf
hexColor: 0xFF0000
""", options);
// Use options for formatting
String formatted = result.toString(options);
System.out.println(formatted);Extend parsing and formatting capabilities with specialized value handlers.
/**
* Interface for implementing Domain Specific Format providers
* DSF providers handle specialized value parsing and formatting
*/
interface IHjsonDsfProvider {
/**
* Gets the name of this DSF provider
* @return the provider name
*/
String getName();
/**
* Gets a description of what this DSF provider handles
* @return the provider description
*/
String getDescription();
/**
* Attempts to parse the given text as a specialized value
* @param text the text to parse
* @return JsonValue representing the parsed value, or null if not handled by this provider
*/
JsonValue parse(String text);
/**
* Attempts to convert the given JsonValue back to specialized string format
* @param value the JsonValue to convert
* @return string representation, or null if not handled by this provider
*/
String stringify(JsonValue value);
}Standard Domain Specific Format providers for common specialized values.
/**
* Utility class providing standard DSF providers
*/
class HjsonDsf {
/**
* Returns a math DSF provider that handles mathematical constants and special values
* Supports: +Inf, -Inf, Inf, +NaN, NaN, -NaN, -0
* @return math DSF provider
*/
static IHjsonDsfProvider math();
/**
* Returns a hex DSF provider that handles hexadecimal number notation
* Parses: 0x prefixed hexadecimal numbers (e.g., 0xFF, 0x123ABC)
* @param stringify whether to format numbers back to hex notation during output
* @return hex DSF provider
*/
static IHjsonDsfProvider hex(boolean stringify);
}Usage Examples:
import org.hjson.HjsonDsf;
import org.hjson.JsonValue;
import org.hjson.HjsonOptions;
import org.hjson.IHjsonDsfProvider;
// Math DSF provider usage
IHjsonDsfProvider mathProvider = HjsonDsf.math();
System.out.println("Math provider: " + mathProvider.getName());
System.out.println("Description: " + mathProvider.getDescription());
// Parse mathematical constants
HjsonOptions mathOptions = new HjsonOptions();
mathOptions.setDsfProviders(new IHjsonDsfProvider[] { mathProvider });
JsonValue infinityValue = JsonValue.readHjson("{ max: +Inf, min: -Inf, invalid: NaN }", mathOptions);
System.out.println("Parsed infinity: " + infinityValue.asObject().get("max").asDouble()); // Infinity
// Hex DSF provider usage
IHjsonDsfProvider hexProvider = HjsonDsf.hex(true); // Enable hex output
HjsonOptions hexOptions = new HjsonOptions();
hexOptions.setDsfProviders(new IHjsonDsfProvider[] { hexProvider });
JsonValue hexValue = JsonValue.readHjson("{ color: 0xFF0000, mask: 0x00FF00 }", hexOptions);
System.out.println("Red color: " + hexValue.asObject().get("color").asInt()); // 16711680
// Combined DSF providers
HjsonOptions combinedOptions = new HjsonOptions();
combinedOptions.setDsfProviders(new IHjsonDsfProvider[] {
HjsonDsf.math(),
HjsonDsf.hex(true)
});
JsonValue combined = JsonValue.readHjson("""
{
maxValue: +Inf
hexColor: 0xFF0000
invalidResult: NaN
bitmask: 0xFFFF
}
""", combinedOptions);
String output = combined.toString(combinedOptions);
System.out.println("Combined output:");
System.out.println(output);Support for parsing Hjson objects without surrounding braces (legacy format).
/**
* Legacy root parsing allows parsing of object members without surrounding braces
* Useful for configuration files that omit the root object braces
*/
boolean getParseLegacyRoot();
void setParseLegacyRoot(boolean value);Usage Examples:
import org.hjson.HjsonOptions;
import org.hjson.JsonValue;
import org.hjson.JsonObject;
// Enable legacy root parsing
HjsonOptions legacyOptions = new HjsonOptions();
legacyOptions.setParseLegacyRoot(true);
// Parse configuration without root braces
String legacyConfig = """
// Application configuration
appName: My Application
version: "1.0.0"
port: 8080
debug: true
// Database settings
dbHost: localhost
dbPort: 5432
dbName: myapp_db
""";
JsonValue config = JsonValue.readHjson(legacyConfig, legacyOptions);
JsonObject configObj = config.asObject();
String appName = configObj.getString("appName", "");
int port = configObj.getInt("port", 3000);
boolean debug = configObj.getBoolean("debug", false);
System.out.println("App: " + appName + ", Port: " + port + ", Debug: " + debug);
// Standard parsing (requires braces)
HjsonOptions standardOptions = new HjsonOptions();
standardOptions.setParseLegacyRoot(false); // Default behavior
try {
JsonValue standard = JsonValue.readHjson(legacyConfig, standardOptions);
// This will throw ParseException because root braces are missing
} catch (ParseException e) {
System.err.println("Standard parsing failed: " + e.getMessage());
}
// Same content with braces works with standard parsing
String bracedConfig = "{ " + legacyConfig + " }";
JsonValue braced = JsonValue.readHjson(bracedConfig, standardOptions);import org.hjson.IHjsonDsfProvider;
import org.hjson.JsonValue;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
/**
* Example DSF provider for ISO date strings
*/
public class DateDsfProvider implements IHjsonDsfProvider {
private static final Pattern ISO_DATE_PATTERN =
Pattern.compile("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?Z?$");
@Override
public String getName() {
return "date";
}
@Override
public String getDescription() {
return "Handles ISO 8601 date strings";
}
@Override
public JsonValue parse(String text) {
if (text != null && ISO_DATE_PATTERN.matcher(text).matches()) {
// Store as string but mark as date for special handling
return JsonValue.valueOf(text);
}
return null; // Not handled by this provider
}
@Override
public String stringify(JsonValue value) {
if (value.isString()) {
String str = value.asString();
if (ISO_DATE_PATTERN.matcher(str).matches()) {
return str; // Return without quotes in Hjson
}
}
return null; // Not handled by this provider
}
}
// Usage
HjsonOptions dateOptions = new HjsonOptions();
dateOptions.setDsfProviders(new IHjsonDsfProvider[] {
new DateDsfProvider(),
HjsonDsf.math()
});
JsonValue dateData = JsonValue.readHjson("""
{
created: 2023-12-01T10:30:00Z
updated: 2023-12-01T15:45:30.123Z
expires: +Inf // Math DSF still works
}
""", dateOptions);/**
* DSF provider for URL validation and handling
*/
public class UrlDsfProvider implements IHjsonDsfProvider {
private static final Pattern URL_PATTERN =
Pattern.compile("^https?://[\\w\\-]+(\\.[\\w\\-]+)*([\\w\\-\\.,@?^=%&:/~\\+#]*[\\w\\-\\@?^=%&/~\\+#])?$");
@Override
public String getName() {
return "url";
}
@Override
public String getDescription() {
return "Handles HTTP and HTTPS URLs";
}
@Override
public JsonValue parse(String text) {
if (text != null && URL_PATTERN.matcher(text).matches()) {
return JsonValue.valueOf(text);
}
return null;
}
@Override
public String stringify(JsonValue value) {
if (value.isString()) {
String str = value.asString();
if (URL_PATTERN.matcher(str).matches()) {
return str; // Output without quotes
}
}
return null;
}
}
// Usage with multiple custom providers
HjsonOptions customOptions = new HjsonOptions();
customOptions.setDsfProviders(new IHjsonDsfProvider[] {
new DateDsfProvider(),
new UrlDsfProvider(),
HjsonDsf.hex(false)
});
JsonValue webConfig = JsonValue.readHjson("""
{
apiEndpoint: https://api.example.com/v1
webhookUrl: https://webhook.example.com/notify
created: 2023-12-01T10:30:00Z
maxRetries: 0xFF // Hex number
}
""", customOptions);import org.hjson.HjsonOptions;
import org.hjson.JsonValue;
import org.hjson.JsonObject;
public class ConfigurationManager {
private final HjsonOptions productionOptions;
private final HjsonOptions developmentOptions;
public ConfigurationManager() {
// Production: strict parsing, minimal DSF
productionOptions = new HjsonOptions();
productionOptions.setParseLegacyRoot(false);
productionOptions.setDsfProviders(new IHjsonDsfProvider[] {
HjsonDsf.math() // Only math constants
});
// Development: lenient parsing, full DSF support
developmentOptions = new HjsonOptions();
developmentOptions.setParseLegacyRoot(true);
developmentOptions.setDsfProviders(new IHjsonDsfProvider[] {
HjsonDsf.math(),
HjsonDsf.hex(true),
new DateDsfProvider(),
new UrlDsfProvider()
});
}
public JsonObject loadConfig(String configText, boolean isProduction) {
HjsonOptions options = isProduction ? productionOptions : developmentOptions;
return JsonValue.readHjson(configText, options).asObject();
}
}public class ChainedDsfProvider implements IHjsonDsfProvider {
private final List<IHjsonDsfProvider> providers;
public ChainedDsfProvider(IHjsonDsfProvider... providers) {
this.providers = Arrays.asList(providers);
}
@Override
public String getName() {
return "chained";
}
@Override
public String getDescription() {
return "Chains multiple DSF providers";
}
@Override
public JsonValue parse(String text) {
for (IHjsonDsfProvider provider : providers) {
JsonValue result = provider.parse(text);
if (result != null) {
return result;
}
}
return null;
}
@Override
public String stringify(JsonValue value) {
for (IHjsonDsfProvider provider : providers) {
String result = provider.stringify(value);
if (result != null) {
return result;
}
}
return null;
}
}
// Usage
HjsonOptions chainedOptions = new HjsonOptions();
chainedOptions.setDsfProviders(new IHjsonDsfProvider[] {
new ChainedDsfProvider(
new DateDsfProvider(),
new UrlDsfProvider(),
HjsonDsf.math(),
HjsonDsf.hex(true)
)
});// Efficient DSF provider implementation
public class OptimizedDsfProvider implements IHjsonDsfProvider {
// Pre-compile patterns for better performance
private static final Pattern PATTERN = Pattern.compile("...");
// Cache compiled patterns and frequently used values
private final Map<String, JsonValue> parseCache = new ConcurrentHashMap<>();
@Override
public JsonValue parse(String text) {
if (text == null || text.isEmpty()) {
return null; // Quick exit for empty strings
}
// Check cache first
JsonValue cached = parseCache.get(text);
if (cached != null) {
return cached;
}
// Perform parsing and cache result
if (PATTERN.matcher(text).matches()) {
JsonValue result = JsonValue.valueOf(text);
parseCache.put(text, result);
return result;
}
return null;
}
}// Good configuration management
public class ConfigManager {
private static final HjsonOptions DEFAULT_OPTIONS = createDefaultOptions();
private static HjsonOptions createDefaultOptions() {
HjsonOptions options = new HjsonOptions();
options.setDsfProviders(new IHjsonDsfProvider[] {
HjsonDsf.math(),
HjsonDsf.hex(true)
});
return options;
}
public static JsonValue parseConfig(String text) {
return JsonValue.readHjson(text, DEFAULT_OPTIONS);
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-hjson--hjson